lib: avb: update and modify the avb library
The commit point is updated to google external/avb/ which commit point is 868db2a514bbb02e166fb55b1592b27de8c9680c. Change-Id: I10f7c0ac356a7666b518b62e59ccb62277668578 Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
This commit is contained in:
parent
eca6f1ffbf
commit
69fdc5969f
|
|
@ -1,94 +1,96 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifdef AVB_INSIDE_LIBAVB_H
|
#ifdef AVB_INSIDE_LIBAVB_H
|
||||||
#error "You can't include avb_sha.h in the public header libavb.h."
|
#error "You can't include avb_sha.h in the public header libavb.h."
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifndef AVB_COMPILATION
|
#ifndef AVB_COMPILATION
|
||||||
#error "Never include this file, it may only be used from internal avb code."
|
#error "Never include this file, it may only be used from internal avb code."
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVB_CMDLINE_H_
|
#ifndef AVB_CMDLINE_H_
|
||||||
#define AVB_CMDLINE_H_
|
#define AVB_CMDLINE_H_
|
||||||
|
|
||||||
#include <android_avb/avb_ops.h>
|
#include <android_avb/avb_ops.h>
|
||||||
#include <android_avb/avb_slot_verify.h>
|
#include <android_avb/avb_slot_verify.h>
|
||||||
|
|
||||||
/* Maximum allow length (in bytes) of a partition name, including
|
/* Maximum allow length (in bytes) of a partition name, including
|
||||||
* ab_suffix.
|
* ab_suffix.
|
||||||
*/
|
*/
|
||||||
#define AVB_PART_NAME_MAX_SIZE 32
|
#define AVB_PART_NAME_MAX_SIZE 32
|
||||||
|
|
||||||
#define AVB_MAX_NUM_CMDLINE_SUBST 10
|
#define AVB_MAX_NUM_CMDLINE_SUBST 10
|
||||||
|
|
||||||
/* Holds information about command-line substitutions. */
|
/* Holds information about command-line substitutions. */
|
||||||
typedef struct AvbCmdlineSubstList {
|
typedef struct AvbCmdlineSubstList {
|
||||||
size_t size;
|
size_t size;
|
||||||
char* tokens[AVB_MAX_NUM_CMDLINE_SUBST];
|
char* tokens[AVB_MAX_NUM_CMDLINE_SUBST];
|
||||||
char* values[AVB_MAX_NUM_CMDLINE_SUBST];
|
char* values[AVB_MAX_NUM_CMDLINE_SUBST];
|
||||||
} AvbCmdlineSubstList;
|
} AvbCmdlineSubstList;
|
||||||
|
|
||||||
/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
|
/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
|
||||||
* values. Returns NULL on OOM, otherwise the cmdline with values
|
* values. Returns NULL on OOM, otherwise the cmdline with values
|
||||||
* replaced.
|
* replaced.
|
||||||
*/
|
*/
|
||||||
char* avb_sub_cmdline(AvbOps* ops,
|
char* avb_sub_cmdline(AvbOps* ops,
|
||||||
const char* cmdline,
|
const char* cmdline,
|
||||||
const char* ab_suffix,
|
const char* ab_suffix,
|
||||||
bool using_boot_for_vbmeta,
|
bool using_boot_for_vbmeta,
|
||||||
const AvbCmdlineSubstList* additional_substitutions);
|
const AvbCmdlineSubstList* additional_substitutions);
|
||||||
|
|
||||||
AvbSlotVerifyResult avb_append_options(
|
AvbSlotVerifyResult avb_append_options(
|
||||||
AvbOps* ops,
|
AvbOps* ops,
|
||||||
AvbSlotVerifyData* slot_data,
|
AvbSlotVerifyFlags flags,
|
||||||
AvbVBMetaImageHeader* toplevel_vbmeta,
|
AvbSlotVerifyData* slot_data,
|
||||||
AvbAlgorithmType algorithm_type,
|
AvbVBMetaImageHeader* toplevel_vbmeta,
|
||||||
AvbHashtreeErrorMode hashtree_error_mode);
|
AvbAlgorithmType algorithm_type,
|
||||||
|
AvbHashtreeErrorMode hashtree_error_mode,
|
||||||
/* Allocates and initializes a new command line substitution list. Free with
|
AvbHashtreeErrorMode resolved_hashtree_error_mode);
|
||||||
* |avb_free_cmdline_subst_list|.
|
|
||||||
*/
|
/* Allocates and initializes a new command line substitution list. Free with
|
||||||
AvbCmdlineSubstList* avb_new_cmdline_subst_list(void);
|
* |avb_free_cmdline_subst_list|.
|
||||||
|
*/
|
||||||
/* Use this instead of |avb_free| to deallocate a AvbCmdlineSubstList. */
|
AvbCmdlineSubstList* avb_new_cmdline_subst_list(void);
|
||||||
void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst);
|
|
||||||
|
/* Use this instead of |avb_free| to deallocate a AvbCmdlineSubstList. */
|
||||||
/* Adds a hashtree root digest to be substituted in $(AVB_*_ROOT_DIGEST)
|
void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst);
|
||||||
* variables. The partition name differentiates the variable. For example, if
|
|
||||||
* |part_name| is "foo" then $(AVB_FOO_ROOT_DIGEST) will be substituted with the
|
/* Adds a hashtree root digest to be substituted in $(AVB_*_ROOT_DIGEST)
|
||||||
* hex encoding of the digest. The substitution will be added to
|
* variables. The partition name differentiates the variable. For example, if
|
||||||
* |out_cmdline_subst|. Returns AVB_SLOT_VERIFY_RESULT_OK on success.
|
* |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
|
||||||
AvbSlotVerifyResult avb_add_root_digest_substitution(
|
* |out_cmdline_subst|. Returns AVB_SLOT_VERIFY_RESULT_OK on success.
|
||||||
const char* part_name,
|
*/
|
||||||
const uint8_t* digest,
|
AvbSlotVerifyResult avb_add_root_digest_substitution(
|
||||||
size_t digest_size,
|
const char* part_name,
|
||||||
AvbCmdlineSubstList* out_cmdline_subst);
|
const uint8_t* digest,
|
||||||
|
size_t digest_size,
|
||||||
#endif
|
AvbCmdlineSubstList* out_cmdline_subst);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,318 +1,348 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||||
#error "Never include this file directly, include libavb.h instead."
|
#error "Never include this file directly, include libavb.h instead."
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVB_OPS_H_
|
#ifndef AVB_OPS_H_
|
||||||
#define AVB_OPS_H_
|
#define AVB_OPS_H_
|
||||||
|
|
||||||
#include <android_avb/avb_sysdeps.h>
|
#include <android_avb/avb_sysdeps.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Well-known names of named persistent values. */
|
/* Well-known names of named persistent values. */
|
||||||
#define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest."
|
#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.
|
|
||||||
*
|
/* Return codes used for I/O operations.
|
||||||
* AVB_IO_RESULT_OK is returned if the requested operation was
|
*
|
||||||
* successful.
|
* 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_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_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_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
|
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
|
||||||
* of the partition.
|
* 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_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_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.
|
* AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small
|
||||||
*/
|
* for the requested operation.
|
||||||
typedef enum {
|
*/
|
||||||
AVB_IO_RESULT_OK,
|
typedef enum {
|
||||||
AVB_IO_RESULT_ERROR_OOM,
|
AVB_IO_RESULT_OK,
|
||||||
AVB_IO_RESULT_ERROR_IO,
|
AVB_IO_RESULT_ERROR_OOM,
|
||||||
AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
|
AVB_IO_RESULT_ERROR_IO,
|
||||||
AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
|
AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
|
||||||
AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
|
AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
|
||||||
AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
|
AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
|
||||||
AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
|
AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
|
||||||
} AvbIOResult;
|
AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
|
||||||
|
} AvbIOResult;
|
||||||
struct AvbOps;
|
|
||||||
typedef struct AvbOps AvbOps;
|
struct AvbOps;
|
||||||
|
typedef struct AvbOps AvbOps;
|
||||||
/* Forward-declaration of operations in libavb_ab. */
|
|
||||||
struct AvbABOps;
|
/* Forward-declaration of operations in libavb_ab. */
|
||||||
|
struct AvbABOps;
|
||||||
/* Forward-declaration of operations in libavb_atx. */
|
|
||||||
struct AvbAtxOps;
|
/* Forward-declaration of operations in libavb_atx. */
|
||||||
|
struct AvbAtxOps;
|
||||||
/* High-level operations/functions/methods that are platform
|
|
||||||
* dependent.
|
/* 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
|
* Operations may be added in the future so when implementing it
|
||||||
* ensure that unimplemented operations are set to NULL.
|
* 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
|
struct AvbOps {
|
||||||
* libavb and is typically used in each operation to get a pointer
|
/* This pointer can be used by the application/bootloader using
|
||||||
* to platform-specific resources. It cannot be used by libraries.
|
* 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;
|
*/
|
||||||
|
void* user_data;
|
||||||
/* If libavb_ab is used, this should point to the
|
|
||||||
* AvbABOps. Otherwise it must be set to NULL.
|
/* If libavb_ab is used, this should point to the
|
||||||
*/
|
* AvbABOps. Otherwise it must be set to NULL.
|
||||||
struct AvbABOps* ab_ops;
|
*/
|
||||||
|
struct AvbABOps* ab_ops;
|
||||||
/* If libavb_atx is used, this should point to the
|
|
||||||
* AvbAtxOps. Otherwise it must be set to NULL.
|
/* If libavb_atx is used, this should point to the
|
||||||
*/
|
* AvbAtxOps. Otherwise it must be set to NULL.
|
||||||
struct AvbAtxOps* atx_ops;
|
*/
|
||||||
|
struct AvbAtxOps* atx_ops;
|
||||||
/* Reads |num_bytes| from offset |offset| from partition with name
|
|
||||||
* |partition| (NUL-terminated UTF-8 string). If |offset| is
|
/* Reads |num_bytes| from offset |offset| from partition with name
|
||||||
* negative, its absolute value should be interpreted as the number
|
* |partition| (NUL-terminated UTF-8 string). If |offset| is
|
||||||
* of bytes from the end of the partition.
|
* 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,
|
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
|
||||||
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
|
* there is no partition with the given name,
|
||||||
* |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
|
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
|
||||||
* there was an I/O error from the underlying I/O subsystem. If the
|
* |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
|
||||||
* operation succeeds as requested AVB_IO_RESULT_OK is returned and
|
* there was an I/O error from the underlying I/O subsystem. If the
|
||||||
* the data is available in |buffer|.
|
* 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
|
* The only time partial I/O may occur is if reading beyond the end
|
||||||
* |out_num_read| may be smaller than |num_bytes|.
|
* 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,
|
AvbIOResult (*read_from_partition)(AvbOps* ops,
|
||||||
int64_t offset,
|
const char* partition,
|
||||||
size_t num_bytes,
|
int64_t offset,
|
||||||
void* buffer,
|
size_t num_bytes,
|
||||||
size_t* out_num_read);
|
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
|
/* Gets the starting pointer of a partition that is pre-loaded in memory, and
|
||||||
* |num_bytes|, where the actual preloaded byte count is returned in
|
* save it to |out_pointer|. The preloaded partition is expected to be
|
||||||
* |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than
|
* |num_bytes|, where the actual preloaded byte count is returned in
|
||||||
* |num_bytes|.
|
* |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
|
* This provides an alternative way to access a partition that is preloaded
|
||||||
* set (has value NULL), or when the |out_pointer| is set to NULL as a result,
|
* into memory without a full memory copy. When this function pointer is not
|
||||||
* |read_from_partition| will be used as the fallback. This function is mainly
|
* set (has value NULL), or when the |out_pointer| is set to NULL as a result,
|
||||||
* used for accessing the entire partition content to calculate its hash.
|
* |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.
|
* 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,
|
AvbIOResult (*get_preloaded_partition)(AvbOps* ops,
|
||||||
size_t num_bytes,
|
const char* partition,
|
||||||
uint8_t** out_pointer,
|
size_t num_bytes,
|
||||||
size_t* out_num_bytes_preloaded);
|
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|
|
/* Writes |num_bytes| from |bffer| at offset |offset| to partition
|
||||||
* is negative, its absolute value should be interpreted as the
|
* with name |partition| (NUL-terminated UTF-8 string). If |offset|
|
||||||
* number of bytes from the end of the partition.
|
* 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,
|
* This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
|
||||||
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
|
* there is no partition with the given name,
|
||||||
* byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
|
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
|
||||||
* if there was an I/O error from the underlying I/O subsystem. If
|
* byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
|
||||||
* the operation succeeds as requested AVB_IO_RESULT_OK is
|
* if there was an I/O error from the underlying I/O subsystem. If
|
||||||
* returned.
|
* 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.
|
* 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,
|
AvbIOResult (*write_to_partition)(AvbOps* ops,
|
||||||
int64_t offset,
|
const char* partition,
|
||||||
size_t num_bytes,
|
int64_t offset,
|
||||||
const void* buffer);
|
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
|
/* Checks if the given public key used to sign the 'vbmeta'
|
||||||
* embedded key material generated with 'avbtool
|
* partition is trusted. Boot loaders typically compare this with
|
||||||
* extract_public_key'.
|
* 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.
|
* 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
|
* If there is no public key metadata (set with the avbtool option
|
||||||
* NULL. Otherwise this field points to the data which is
|
* --public_key_metadata) then |public_key_metadata| will be set to
|
||||||
* |public_key_metadata_length| bytes long.
|
* 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.
|
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
|
||||||
*/
|
* true if trusted or false if untrusted.
|
||||||
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
|
*
|
||||||
const uint8_t* public_key_data,
|
* NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
|
||||||
size_t public_key_length,
|
* avb_slot_verify() then this operation is never used. Instead, the
|
||||||
const uint8_t* public_key_metadata,
|
* validate_public_key_for_partition() operation is used
|
||||||
size_t public_key_metadata_length,
|
*/
|
||||||
bool* out_is_trusted);
|
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
|
||||||
|
const uint8_t* public_key_data,
|
||||||
/* Gets the rollback index corresponding to the location given by
|
size_t public_key_length,
|
||||||
* |rollback_index_location|. The value is returned in
|
const uint8_t* public_key_metadata,
|
||||||
* |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
|
size_t public_key_metadata_length,
|
||||||
* index was retrieved, otherwise an error code.
|
bool* out_is_trusted);
|
||||||
*
|
|
||||||
* A device may have a limited amount of rollback index locations (say,
|
/* Gets the rollback index corresponding to the location given by
|
||||||
* one or four) so may error out if |rollback_index_location| exceeds
|
* |rollback_index_location|. The value is returned in
|
||||||
* this number.
|
* |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
|
||||||
*/
|
* index was retrieved, otherwise an error code.
|
||||||
AvbIOResult (*read_rollback_index)(AvbOps* ops,
|
*
|
||||||
size_t rollback_index_location,
|
* A device may have a limited amount of rollback index locations (say,
|
||||||
uint64_t* out_rollback_index);
|
* one or four) so may error out if |rollback_index_location| exceeds
|
||||||
|
* this number.
|
||||||
/* Sets the rollback index corresponding to the location given by
|
*/
|
||||||
* |rollback_index_location| to |rollback_index|. Returns
|
AvbIOResult (*read_rollback_index)(AvbOps* ops,
|
||||||
* AVB_IO_RESULT_OK if the rollback index was set, otherwise an
|
size_t rollback_index_location,
|
||||||
* error code.
|
uint64_t* out_rollback_index);
|
||||||
*
|
|
||||||
* A device may have a limited amount of rollback index locations (say,
|
/* Sets the rollback index corresponding to the location given by
|
||||||
* one or four) so may error out if |rollback_index_location| exceeds
|
* |rollback_index_location| to |rollback_index|. Returns
|
||||||
* this number.
|
* AVB_IO_RESULT_OK if the rollback index was set, otherwise an
|
||||||
*/
|
* error code.
|
||||||
AvbIOResult (*write_rollback_index)(AvbOps* ops,
|
*
|
||||||
size_t rollback_index_location,
|
* A device may have a limited amount of rollback index locations (say,
|
||||||
uint64_t rollback_index);
|
* one or four) so may error out if |rollback_index_location| exceeds
|
||||||
|
* this number.
|
||||||
/* Gets whether the device is unlocked. The value is returned in
|
*/
|
||||||
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
|
AvbIOResult (*write_rollback_index)(AvbOps* ops,
|
||||||
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
|
size_t rollback_index_location,
|
||||||
* code.
|
uint64_t rollback_index);
|
||||||
*/
|
|
||||||
AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
|
/* Gets whether the device is unlocked. The value is returned in
|
||||||
|
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
|
||||||
/* write the device lock flag. Returns
|
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
|
||||||
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
|
* code.
|
||||||
* code.
|
*/
|
||||||
*/
|
AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
|
||||||
AvbIOResult (*write_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
|
|
||||||
/* Gets the unique partition GUID for a partition with name in
|
/* write the device lock flag. Returns
|
||||||
* |partition| (NUL-terminated UTF-8 string). The GUID is copied as
|
* AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
|
||||||
* a string into |guid_buf| of size |guid_buf_size| and will be NUL
|
* code.
|
||||||
* terminated. The string must be lower-case and properly
|
*/
|
||||||
* hyphenated. For example:
|
AvbIOResult (*write_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
|
||||||
*
|
|
||||||
* 527c1c6d-6361-4593-8842-3c78fcd39219
|
/* Gets the unique partition GUID for a partition with name in
|
||||||
*
|
* |partition| (NUL-terminated UTF-8 string). The GUID is copied as
|
||||||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
* a string into |guid_buf| of size |guid_buf_size| and will be NUL
|
||||||
*/
|
* terminated. The string must be lower-case and properly
|
||||||
AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
|
* hyphenated. For example:
|
||||||
const char* partition,
|
*
|
||||||
char* guid_buf,
|
* 527c1c6d-6361-4593-8842-3c78fcd39219
|
||||||
size_t guid_buf_size);
|
*
|
||||||
|
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||||
/* Gets the size of a partition with the name in |partition|
|
*/
|
||||||
* (NUL-terminated UTF-8 string). Returns the value in
|
AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
|
||||||
* |out_size_num_bytes|.
|
const char* partition,
|
||||||
*
|
char* guid_buf,
|
||||||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
size_t guid_buf_size);
|
||||||
*/
|
|
||||||
AvbIOResult (*get_size_of_partition)(AvbOps* ops,
|
/* Gets the size of a partition with the name in |partition|
|
||||||
const char* partition,
|
* (NUL-terminated UTF-8 string). Returns the value in
|
||||||
uint64_t* out_size_num_bytes);
|
* |out_size_num_bytes|.
|
||||||
|
*
|
||||||
/* Reads a persistent value corresponding to the given |name|. The value is
|
* If the partition doesn't exist the AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION
|
||||||
* returned in |out_buffer| which must point to |buffer_size| bytes. On
|
* error code should be returned.
|
||||||
* success |out_num_bytes_read| contains the number of bytes read into
|
*
|
||||||
* |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned,
|
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||||
* |out_num_bytes_read| contains the number of bytes that would have been read
|
*/
|
||||||
* which can be used to allocate a buffer.
|
AvbIOResult (*get_size_of_partition)(AvbOps* ops,
|
||||||
*
|
const char* partition,
|
||||||
* The |buffer_size| may be zero and the |out_buffer| may be NULL, but if
|
uint64_t* out_size_num_bytes);
|
||||||
* |out_buffer| is NULL then |buffer_size| *must* be zero.
|
|
||||||
*
|
/* Reads a persistent value corresponding to the given |name|. The value is
|
||||||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
* returned in |out_buffer| which must point to |buffer_size| bytes. On
|
||||||
*
|
* success |out_num_bytes_read| contains the number of bytes read into
|
||||||
* If the value does not exist, is not supported, or is not populated, returns
|
* |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned,
|
||||||
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the
|
* |out_num_bytes_read| contains the number of bytes that would have been read
|
||||||
* size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE.
|
* which can be used to allocate a buffer.
|
||||||
*
|
*
|
||||||
* This operation is currently only used to support persistent digests. If a
|
* The |buffer_size| may be zero and the |out_buffer| may be NULL, but if
|
||||||
* device does not use persistent digests this function pointer can be set to
|
* |out_buffer| is NULL then |buffer_size| *must* be zero.
|
||||||
* NULL.
|
*
|
||||||
*/
|
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||||
AvbIOResult (*read_persistent_value)(AvbOps* ops,
|
*
|
||||||
const char* name,
|
* If the value does not exist, is not supported, or is not populated, returns
|
||||||
size_t buffer_size,
|
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the
|
||||||
uint8_t* out_buffer,
|
* size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE.
|
||||||
size_t* out_num_bytes_read);
|
*
|
||||||
|
* This operation is currently only used to support persistent digests or the
|
||||||
/* Writes a persistent value corresponding to the given |name|. The value is
|
* AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a
|
||||||
* supplied in |value| which must point to |value_size| bytes. Any existing
|
* device does not use one of these features this function pointer can be set
|
||||||
* value with the same name is overwritten. If |value_size| is zero, future
|
* to NULL.
|
||||||
* calls to |read_persistent_value| will return
|
*/
|
||||||
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE.
|
AvbIOResult (*read_persistent_value)(AvbOps* ops,
|
||||||
*
|
const char* name,
|
||||||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
size_t buffer_size,
|
||||||
*
|
uint8_t* out_buffer,
|
||||||
* If the value |name| is not supported, returns
|
size_t* out_num_bytes_read);
|
||||||
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported,
|
|
||||||
* returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE.
|
/* Writes a persistent value corresponding to the given |name|. The value is
|
||||||
*
|
* supplied in |value| which must point to |value_size| bytes. Any existing
|
||||||
* This operation is currently only used to support persistent digests. If a
|
* value with the same name is overwritten. If |value_size| is zero, future
|
||||||
* device does not use persistent digests this function pointer can be set to
|
* calls to |read_persistent_value| will return
|
||||||
* NULL.
|
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE.
|
||||||
*/
|
*
|
||||||
AvbIOResult (*write_persistent_value)(AvbOps* ops,
|
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||||
const char* name,
|
*
|
||||||
size_t value_size,
|
* If the value |name| is not supported, returns
|
||||||
const uint8_t* value);
|
* AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported,
|
||||||
};
|
* returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE.
|
||||||
|
*
|
||||||
#ifdef __cplusplus
|
* 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
|
||||||
#endif
|
* device does not use one of these features this function pointer can be set
|
||||||
|
* to NULL.
|
||||||
#endif /* AVB_OPS_H_ */
|
*/
|
||||||
|
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_ */
|
||||||
|
|
|
||||||
|
|
@ -1,92 +1,92 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifdef AVB_INSIDE_LIBAVB_H
|
#ifdef AVB_INSIDE_LIBAVB_H
|
||||||
#error "You can't include avb_sha.h in the public header libavb.h."
|
#error "You can't include avb_sha.h in the public header libavb.h."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef AVB_COMPILATION
|
#ifndef AVB_COMPILATION
|
||||||
#error "Never include this file, it may only be used from internal avb code."
|
#error "Never include this file, it may only be used from internal avb code."
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVB_SHA_H_
|
#ifndef AVB_SHA_H_
|
||||||
#define AVB_SHA_H_
|
#define AVB_SHA_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <android_avb/avb_crypto.h>
|
#include <android_avb/avb_crypto.h>
|
||||||
#include <android_avb/avb_sysdeps.h>
|
#include <android_avb/avb_sysdeps.h>
|
||||||
|
|
||||||
/* Block size in bytes of a SHA-256 digest. */
|
/* Block size in bytes of a SHA-256 digest. */
|
||||||
#define AVB_SHA256_BLOCK_SIZE 64
|
#define AVB_SHA256_BLOCK_SIZE 64
|
||||||
|
|
||||||
|
|
||||||
/* Block size in bytes of a SHA-512 digest. */
|
/* Block size in bytes of a SHA-512 digest. */
|
||||||
#define AVB_SHA512_BLOCK_SIZE 128
|
#define AVB_SHA512_BLOCK_SIZE 128
|
||||||
|
|
||||||
/* Data structure used for SHA-256. */
|
/* Data structure used for SHA-256. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t h[8];
|
uint32_t h[8];
|
||||||
uint32_t tot_len;
|
uint64_t tot_len;
|
||||||
uint32_t len;
|
size_t len;
|
||||||
uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
|
uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
|
||||||
uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
|
uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
|
||||||
} AvbSHA256Ctx;
|
} AvbSHA256Ctx;
|
||||||
|
|
||||||
/* Data structure used for SHA-512. */
|
/* Data structure used for SHA-512. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t h[8];
|
uint64_t h[8];
|
||||||
uint32_t tot_len;
|
uint64_t tot_len;
|
||||||
uint32_t len;
|
size_t len;
|
||||||
uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
|
uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
|
||||||
uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
|
uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
|
||||||
} AvbSHA512Ctx;
|
} AvbSHA512Ctx;
|
||||||
|
|
||||||
/* Initializes the SHA-256 context. */
|
/* Initializes the SHA-256 context. */
|
||||||
void avb_sha256_init(AvbSHA256Ctx* ctx);
|
void avb_sha256_init(AvbSHA256Ctx* ctx);
|
||||||
|
|
||||||
/* Updates the SHA-256 context with |len| bytes from |data|. */
|
/* Updates the SHA-256 context with |len| bytes from |data|. */
|
||||||
void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len);
|
void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len);
|
||||||
|
|
||||||
/* Returns the SHA-256 digest. */
|
/* Returns the SHA-256 digest. */
|
||||||
uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
|
uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Initializes the SHA-512 context. */
|
/* Initializes the SHA-512 context. */
|
||||||
void avb_sha512_init(AvbSHA512Ctx* ctx);
|
void avb_sha512_init(AvbSHA512Ctx* ctx);
|
||||||
|
|
||||||
/* Updates the SHA-512 context with |len| bytes from |data|. */
|
/* Updates the SHA-512 context with |len| bytes from |data|. */
|
||||||
void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len);
|
void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len);
|
||||||
|
|
||||||
/* Returns the SHA-512 digest. */
|
/* Returns the SHA-512 digest. */
|
||||||
uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
|
uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* AVB_SHA_H_ */
|
#endif /* AVB_SHA_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1,361 +1,402 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||||
#error "Never include this file directly, include libavb.h instead."
|
#error "Never include this file directly, include libavb.h instead."
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVB_SLOT_VERIFY_H_
|
#ifndef AVB_SLOT_VERIFY_H_
|
||||||
#define AVB_SLOT_VERIFY_H_
|
#define AVB_SLOT_VERIFY_H_
|
||||||
|
|
||||||
#include <android_avb/avb_ops.h>
|
#include <android_avb/avb_ops.h>
|
||||||
#include <android_avb/avb_vbmeta_image.h>
|
#include <android_avb/avb_vbmeta_image.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Return codes used in avb_slot_verify(), see that function for
|
/* Return codes used in avb_slot_verify(), see that function for
|
||||||
* documentation for each field.
|
* documentation for each field.
|
||||||
*
|
*
|
||||||
* Use avb_slot_verify_result_to_string() to get a textual
|
* Use avb_slot_verify_result_to_string() to get a textual
|
||||||
* representation usable for error/debug output.
|
* representation usable for error/debug output.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AVB_SLOT_VERIFY_RESULT_OK,
|
AVB_SLOT_VERIFY_RESULT_OK,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
|
AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_IO,
|
AVB_SLOT_VERIFY_RESULT_ERROR_IO,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
|
AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
|
AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
|
AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
|
AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
|
AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
|
||||||
AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
|
AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
|
||||||
} AvbSlotVerifyResult;
|
} AvbSlotVerifyResult;
|
||||||
|
|
||||||
/* Various error handling modes for when verification fails using a
|
/* Various error handling modes for when verification fails using a
|
||||||
* hashtree at runtime inside the HLOS.
|
* hashtree at runtime inside the HLOS.
|
||||||
*
|
*
|
||||||
* AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
|
* AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
|
||||||
* will invalidate the current slot and restart.
|
* will invalidate the current slot and restart.
|
||||||
*
|
*
|
||||||
* AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
|
* AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
|
||||||
*
|
*
|
||||||
* AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
|
* AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
|
||||||
* returned to applications.
|
* returned to applications.
|
||||||
*
|
*
|
||||||
* AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
|
* AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
|
||||||
* and corrupt data may be returned to applications. This mode should
|
* and corrupt data may be returned to applications. This mode should
|
||||||
* be used ONLY for diagnostics and debugging. It cannot be used
|
* be used ONLY for diagnostics and debugging. It cannot be used
|
||||||
* unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
|
* unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
|
||||||
* used.
|
* used.
|
||||||
*/
|
*
|
||||||
typedef enum {
|
* AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO means that either
|
||||||
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
|
* AVB_HASHTREE_ERROR_MODE_RESTART or AVB_HASHTREE_ERROR_MODE_EIO is used
|
||||||
AVB_HASHTREE_ERROR_MODE_RESTART,
|
* depending on state. This mode implements a state machine whereby
|
||||||
AVB_HASHTREE_ERROR_MODE_EIO,
|
* AVB_HASHTREE_ERROR_MODE_RESTART is used by default and when
|
||||||
AVB_HASHTREE_ERROR_MODE_LOGGING
|
* AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION is passed the
|
||||||
} AvbHashtreeErrorMode;
|
* 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
|
||||||
/* Flags that influence how avb_slot_verify() works.
|
* 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
|
||||||
* If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
|
* write_persistent_value() operations implemented. The name of the persistent
|
||||||
* avb_slot_verify() will bail out as soon as an error is encountered
|
* value used is "avb.managed_verity_mode" and 32 bytes of storage is needed.
|
||||||
* and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
|
*/
|
||||||
* returned.
|
typedef enum {
|
||||||
*
|
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
|
||||||
* Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
|
AVB_HASHTREE_ERROR_MODE_RESTART,
|
||||||
* avb_slot_verify() will continue verification efforts and |out_data|
|
AVB_HASHTREE_ERROR_MODE_EIO,
|
||||||
* is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
|
AVB_HASHTREE_ERROR_MODE_LOGGING,
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
|
AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
|
} AvbHashtreeErrorMode;
|
||||||
* undefined which error is returned if more than one distinct error
|
|
||||||
* is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
|
/* Flags that influence how avb_slot_verify() works.
|
||||||
* returned if, and only if, there are no errors. This mode is needed
|
*
|
||||||
* to boot valid but unverified slots when the device is unlocked.
|
* 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
|
||||||
* Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
|
* and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
|
||||||
* contents loaded from |requested_partition| will be the contents of
|
* returned.
|
||||||
* the entire partition instead of just the size specified in the hash
|
*
|
||||||
* descriptor.
|
* Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
|
||||||
*/
|
* avb_slot_verify() will continue verification efforts and |out_data|
|
||||||
typedef enum {
|
* is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
|
||||||
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
|
* AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
|
||||||
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
|
* AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
|
||||||
} AvbSlotVerifyFlags;
|
* undefined which error is returned if more than one distinct error
|
||||||
|
* is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
|
||||||
/* Get a textual representation of |result|. */
|
* returned if, and only if, there are no errors. This mode is needed
|
||||||
const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
|
* to boot valid but unverified slots when the device is unlocked.
|
||||||
|
*
|
||||||
/* Maximum number of rollback index locations supported. */
|
* Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
|
||||||
#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
|
* contents loaded from |requested_partition| will be the contents of
|
||||||
|
* the entire partition instead of just the size specified in the hash
|
||||||
/* AvbPartitionData contains data loaded from partitions when using
|
* descriptor.
|
||||||
* avb_slot_verify(). The |partition_name| field contains the name of
|
*
|
||||||
* the partition (without A/B suffix), |data| points to the loaded
|
* The AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION flag
|
||||||
* data which is |data_size| bytes long. If |preloaded| is set to true,
|
* should be set if using AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
|
||||||
* this structure dose not own |data|. The caller of |avb_slot_verify|
|
* and the reason the boot loader is running is because the device
|
||||||
* needs to make sure that the preloaded data outlives this
|
* was restarted by the dm-verity driver.
|
||||||
* |AvbPartitionData| structure.
|
*
|
||||||
*
|
* If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
|
||||||
* Note that this is strictly less than the partition size - it's only
|
* data won't be loaded from the "vbmeta" partition and the
|
||||||
* the image stored there, not the entire partition nor any of the
|
* |validate_vbmeta_public_key| operation is never called. Instead, the
|
||||||
* metadata.
|
* vbmeta structs in |requested_partitions| are loaded and processed and the
|
||||||
*/
|
* |validate_public_key_for_partition| operation is called for each of these
|
||||||
typedef struct {
|
* vbmeta structs. This flag is useful when booting into recovery on a device
|
||||||
char* partition_name;
|
* not using A/B - see section "Booting into recovery" in README.md for
|
||||||
uint8_t* data;
|
* more information.
|
||||||
size_t data_size;
|
*/
|
||||||
bool preloaded;
|
typedef enum {
|
||||||
} AvbPartitionData;
|
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
|
||||||
|
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
|
||||||
/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
|
AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
|
||||||
* using avb_slot_verify(). The |partition_name| field contains the
|
AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
|
||||||
* name of the partition (without A/B suffix), |vbmeta_data| points to
|
} AvbSlotVerifyFlags;
|
||||||
* the loaded data which is |vbmeta_size| bytes long.
|
|
||||||
*
|
/* Get a textual representation of |result|. */
|
||||||
* The |verify_result| field contains the result of
|
const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
|
||||||
* avb_vbmeta_image_verify() on the data. This is guaranteed to be
|
|
||||||
* AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
|
/* Maximum number of rollback index locations supported. */
|
||||||
* avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
|
#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
|
||||||
*
|
|
||||||
* You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
|
/* AvbPartitionData contains data loaded from partitions when using
|
||||||
* avb_vbmeta_image_header_to_host_byte_order() with this data.
|
* avb_slot_verify(). The |partition_name| field contains the name of
|
||||||
*/
|
* the partition (without A/B suffix), |data| points to the loaded
|
||||||
typedef struct {
|
* data which is |data_size| bytes long. If |preloaded| is set to true,
|
||||||
char* partition_name;
|
* this structure dose not own |data|. The caller of |avb_slot_verify|
|
||||||
uint8_t* vbmeta_data;
|
* needs to make sure that the preloaded data outlives this
|
||||||
size_t vbmeta_size;
|
* |AvbPartitionData| structure.
|
||||||
AvbVBMetaVerifyResult verify_result;
|
*
|
||||||
} AvbVBMetaData;
|
* 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
|
||||||
/* AvbSlotVerifyData contains data needed to boot a particular slot
|
* metadata.
|
||||||
* and is returned by avb_slot_verify() if partitions in a slot are
|
*/
|
||||||
* successfully verified.
|
typedef struct {
|
||||||
*
|
char* partition_name;
|
||||||
* All data pointed to by this struct - including data in each item in
|
uint8_t* data;
|
||||||
* the |partitions| array - will be freed when the
|
size_t data_size;
|
||||||
* avb_slot_verify_data_free() function is called.
|
bool preloaded;
|
||||||
*
|
} AvbPartitionData;
|
||||||
* 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
|
/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
|
||||||
* value includes the leading underscore - typical values are "" (if
|
* using avb_slot_verify(). The |partition_name| field contains the
|
||||||
* no slots are in use), "_a" (for the first slot), and "_b" (for the
|
* name of the partition (without A/B suffix), |vbmeta_data| points to
|
||||||
* second slot).
|
* the loaded data which is |vbmeta_size| bytes long.
|
||||||
*
|
*
|
||||||
* The VBMeta images that were checked are available in the
|
* The |verify_result| field contains the result of
|
||||||
* |vbmeta_images| field. The field |num_vbmeta_images| contains the
|
* avb_vbmeta_image_verify() on the data. This is guaranteed to be
|
||||||
* number of elements in this array. The first element -
|
* AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
|
||||||
* vbmeta_images[0] - is guaranteed to be from the partition with the
|
* avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
|
||||||
* top-level vbmeta struct. This is usually the "vbmeta" partition in
|
*
|
||||||
* the requested slot but if there is no "vbmeta" partition it can
|
* You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
|
||||||
* also be the "boot" partition.
|
* avb_vbmeta_image_header_to_host_byte_order() with this data.
|
||||||
*
|
*/
|
||||||
* The partitions loaded and verified from from the slot are
|
typedef struct {
|
||||||
* accessible in the |loaded_partitions| array. The field
|
char* partition_name;
|
||||||
* |num_loaded_partitions| contains the number of elements in this
|
uint8_t* vbmeta_data;
|
||||||
* array. The order of partitions in this array may not necessarily be
|
size_t vbmeta_size;
|
||||||
* the same order as in the passed-in |requested_partitions| array.
|
AvbVBMetaVerifyResult verify_result;
|
||||||
*
|
} AvbVBMetaData;
|
||||||
* Rollback indexes for the verified slot are stored in the
|
|
||||||
* |rollback_indexes| field. Note that avb_slot_verify() will NEVER
|
/* AvbSlotVerifyData contains data needed to boot a particular slot
|
||||||
* modify stored_rollback_index[n] locations e.g. it will never use
|
* and is returned by avb_slot_verify() if partitions in a slot are
|
||||||
* the write_rollback_index() AvbOps operation. Instead it is the job
|
* successfully verified.
|
||||||
* 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
|
* All data pointed to by this struct - including data in each item in
|
||||||
* example of how to do this.
|
* the |partitions| array - will be freed when the
|
||||||
*
|
* avb_slot_verify_data_free() function is called.
|
||||||
* The |cmdline| field is a NUL-terminated string in UTF-8 resulting
|
*
|
||||||
* from concatenating all |AvbKernelCmdlineDescriptor| and then
|
* The |ab_suffix| field is the copy of the of |ab_suffix| field
|
||||||
* performing proper substitution of the variables
|
* passed to avb_slot_verify(). It is the A/B suffix of the slot. This
|
||||||
* $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
|
* value includes the leading underscore - typical values are "" (if
|
||||||
* $(ANDROID_VBMETA_PARTUUID) using the
|
* no slots are in use), "_a" (for the first slot), and "_b" (for the
|
||||||
* get_unique_guid_for_partition() operation in |AvbOps|. Additionally
|
* second slot).
|
||||||
* $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
|
*
|
||||||
* option depending on the value of |hashtree_error_mode|.
|
* The VBMeta images that were checked are available in the
|
||||||
*
|
* |vbmeta_images| field. The field |num_vbmeta_images| contains the
|
||||||
* Additionally, the |cmdline| field will have the following kernel
|
* number of elements in this array. The first element -
|
||||||
* command-line options set (unless verification is disabled, see
|
* vbmeta_images[0] - is guaranteed to be from the partition with the
|
||||||
* below):
|
* top-level vbmeta struct. This is usually the "vbmeta" partition in
|
||||||
*
|
* the requested slot but if there is no "vbmeta" partition it can
|
||||||
* androidboot.veritymode: This is set to 'disabled' if the
|
* also be the "boot" partition.
|
||||||
* AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
|
*
|
||||||
* vbmeta struct. Otherwise it is set to 'enforcing' if the
|
* The partitions loaded and verified from from the slot are
|
||||||
* passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
|
* accessible in the |loaded_partitions| array. The field
|
||||||
* or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
|
* |num_loaded_partitions| contains the number of elements in this
|
||||||
* set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
|
* array. The order of partitions in this array may not necessarily be
|
||||||
* AVB_HASHTREE_ERROR_MODE_LOGGING.
|
* the same order as in the passed-in |requested_partitions| array.
|
||||||
*
|
*
|
||||||
* androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
|
* Rollback indexes for the verified slot are stored in the
|
||||||
* if hashtree validation isn't disabled and the passed-in hashtree
|
* |rollback_indexes| field. Note that avb_slot_verify() will NEVER
|
||||||
* error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
|
* modify stored_rollback_index[n] locations e.g. it will never use
|
||||||
*
|
* the write_rollback_index() AvbOps operation. Instead it is the job
|
||||||
* androidboot.vbmeta.device_state: set to "locked" or "unlocked"
|
* of the caller of avb_slot_verify() to do this based on e.g. A/B
|
||||||
* depending on the result of the result of AvbOps's
|
* policy and other factors. See libavb_ab/avb_ab_flow.c for an
|
||||||
* read_is_unlocked() function.
|
* example of how to do this.
|
||||||
*
|
*
|
||||||
* androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
|
* The |cmdline| field is a NUL-terminated string in UTF-8 resulting
|
||||||
* the digest of all images in |vbmeta_images|.
|
* from concatenating all |AvbKernelCmdlineDescriptor| and then
|
||||||
*
|
* performing proper substitution of the variables
|
||||||
* androidboot.vbmeta.device: This is set to the value
|
* $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
|
||||||
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
|
* $(ANDROID_VBMETA_PARTUUID) using the
|
||||||
* will end up pointing to the vbmeta partition for the verified
|
* get_unique_guid_for_partition() operation in |AvbOps|. Additionally
|
||||||
* slot. If there is no vbmeta partition it will point to the boot
|
* $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
|
||||||
* partition of the verified slot.
|
* option depending on the value of |hashtree_error_mode|.
|
||||||
*
|
*
|
||||||
* androidboot.vbmeta.avb_version: This is set to the decimal value
|
* Additionally, the |cmdline| field will have the following kernel
|
||||||
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal
|
* command-line options set (unless verification is disabled, see
|
||||||
* value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
|
* below):
|
||||||
* version number represents the vbmeta file format version
|
*
|
||||||
* supported by libavb copy used in the boot loader. This is not
|
* androidboot.veritymode: This is set to 'disabled' if the
|
||||||
* necessarily the same version number of the on-disk metadata for
|
* AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
|
||||||
* the slot that was verified.
|
* vbmeta struct. Otherwise it is set to 'enforcing' if the
|
||||||
*
|
* passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
|
||||||
* Note that androidboot.slot_suffix is not set in the |cmdline| field
|
* or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
|
||||||
* in |AvbSlotVerifyData| - you will have to set this yourself.
|
* set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
|
||||||
*
|
* AVB_HASHTREE_ERROR_MODE_LOGGING.
|
||||||
* If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
|
*
|
||||||
* in the top-level vbmeta struct then only the top-level vbmeta
|
* androidboot.veritymode.managed: This is set to 'yes' only
|
||||||
* struct is verified and descriptors will not processed. The return
|
* if hashtree validation isn't disabled and the passed-in hashtree
|
||||||
* value will be set accordingly (if this flag is set via 'avbctl
|
* error mode is AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO.
|
||||||
* disable-verification' then the return value will be
|
*
|
||||||
* |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
|
* androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
|
||||||
* |AvbSlotVerifyData| is returned. Additionally all partitions in the
|
* if hashtree validation isn't disabled and the passed-in hashtree
|
||||||
* |requested_partitions| are loaded and the |cmdline| field is set to
|
* error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
|
||||||
* "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
|
*
|
||||||
* appropriate system partition is substituted in. Note that none of
|
* androidboot.vbmeta.device_state: set to "locked" or "unlocked"
|
||||||
* the androidboot.* options mentioned above will be set.
|
* depending on the result of the result of AvbOps's
|
||||||
*
|
* read_is_unlocked() function.
|
||||||
* This struct may grow in the future without it being considered an
|
*
|
||||||
* ABI break.
|
* androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
|
||||||
*/
|
* the digest of all images in |vbmeta_images|.
|
||||||
typedef struct {
|
*
|
||||||
char* ab_suffix;
|
* androidboot.vbmeta.device: This is set to the value
|
||||||
AvbVBMetaData* vbmeta_images;
|
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
|
||||||
size_t num_vbmeta_images;
|
* will end up pointing to the vbmeta partition for the verified
|
||||||
AvbPartitionData* loaded_partitions;
|
* slot. If there is no vbmeta partition it will point to the boot
|
||||||
size_t num_loaded_partitions;
|
* partition of the verified slot. If the flag
|
||||||
char* cmdline;
|
* AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
|
||||||
uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
|
* set.
|
||||||
} AvbSlotVerifyData;
|
*
|
||||||
|
* androidboot.vbmeta.avb_version: This is set to the decimal value
|
||||||
/* Calculates a digest of all vbmeta images in |data| using
|
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal
|
||||||
* the digest indicated by |digest_type|. Stores the result
|
* value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
|
||||||
* in |out_digest| which must be large enough to hold a digest
|
* version number represents the vbmeta file format version
|
||||||
* of the requested type.
|
* supported by libavb copy used in the boot loader. This is not
|
||||||
*/
|
* necessarily the same version number of the on-disk metadata for
|
||||||
void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
|
* the slot that was verified.
|
||||||
AvbDigestType digest_type,
|
*
|
||||||
uint8_t* out_digest);
|
* Note that androidboot.slot_suffix is not set in the |cmdline| field
|
||||||
|
* in |AvbSlotVerifyData| - you will have to set this yourself.
|
||||||
/* Frees a |AvbSlotVerifyData| including all data it points to. */
|
*
|
||||||
void avb_slot_verify_data_free(AvbSlotVerifyData* data);
|
* If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
|
||||||
|
* in the top-level vbmeta struct then only the top-level vbmeta
|
||||||
/* Performs a full verification of the slot identified by |ab_suffix|
|
* struct is verified and descriptors will not processed. The return
|
||||||
* and load and verify the contents of the partitions whose name is in
|
* value will be set accordingly (if this flag is set via 'avbctl
|
||||||
* the NULL-terminated string array |requested_partitions| (each
|
* disable-verification' then the return value will be
|
||||||
* partition must use hash verification). If not using A/B, pass an
|
* |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
|
||||||
* empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
|
* |AvbSlotVerifyData| is returned. Additionally all partitions in the
|
||||||
* must include the leading underscore, for example "_a" should be
|
* |requested_partitions| are loaded and the |cmdline| field is set to
|
||||||
* used to refer to the first slot.
|
* "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
|
||||||
*
|
* appropriate system partition is substituted in. Note that none of
|
||||||
* Typically the |requested_partitions| array only contains a single
|
* the androidboot.* options mentioned above will be set.
|
||||||
* item for the boot partition, 'boot'.
|
*
|
||||||
*
|
* The |resolved_hashtree_error_mode| is the the value of the passed
|
||||||
* Verification includes loading and verifying data from the 'vbmeta',
|
* avb_slot_verify()'s |hashtree_error_mode| parameter except that it never has
|
||||||
* the requested hash partitions, and possibly other partitions (with
|
* the value AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO. If this value was
|
||||||
* |ab_suffix| appended), inspecting rollback indexes, and checking if
|
* passed in, then the restart/eio state machine is used resulting in
|
||||||
* the public key used to sign the data is acceptable. The functions
|
* |resolved_hashtree_error_mode| being set to either
|
||||||
* in |ops| will be used to do this.
|
* 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
|
||||||
* If |out_data| is not NULL, it will be set to a newly allocated
|
* screen for the user to click through before continuing to boot.
|
||||||
* |AvbSlotVerifyData| struct containing all the data needed to
|
*
|
||||||
* actually boot the slot. This data structure should be freed with
|
* This struct may grow in the future without it being considered an
|
||||||
* avb_slot_verify_data_free() when you are done with it. See below
|
* ABI break.
|
||||||
* for when this is returned.
|
*/
|
||||||
*
|
typedef struct {
|
||||||
* The |flags| parameter is used to influence the semantics of
|
char* ab_suffix;
|
||||||
* avb_slot_verify() - for example the
|
AvbVBMetaData* vbmeta_images;
|
||||||
* AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
|
size_t num_vbmeta_images;
|
||||||
* ignore verification errors which is something needed in the
|
AvbPartitionData* loaded_partitions;
|
||||||
* UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
|
size_t num_loaded_partitions;
|
||||||
*
|
char* cmdline;
|
||||||
* The |hashtree_error_mode| parameter should be set to the desired
|
uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
|
||||||
* error handling mode when hashtree validation fails inside the
|
AvbHashtreeErrorMode resolved_hashtree_error_mode;
|
||||||
* HLOS. This value isn't used by libavb per se - it is forwarded to
|
} AvbSlotVerifyData;
|
||||||
* the HLOS through the androidboot.veritymode and
|
|
||||||
* androidboot.vbmeta.invalidate_on_error cmdline parameters. See the
|
/* Calculates a digest of all vbmeta images in |data| using
|
||||||
* AvbHashtreeErrorMode enumeration for details.
|
* the digest indicated by |digest_type|. Stores the result
|
||||||
*
|
* in |out_digest| which must be large enough to hold a digest
|
||||||
* Also note that |out_data| is never set if
|
* of the requested type.
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
|
*/
|
||||||
* or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
|
void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
|
||||||
*
|
AvbDigestType digest_type,
|
||||||
* AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
|
uint8_t* out_digest);
|
||||||
* correctly and all public keys are accepted.
|
|
||||||
*
|
/* Frees a |AvbSlotVerifyData| including all data it points to. */
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED is returned if
|
void avb_slot_verify_data_free(AvbSlotVerifyData* data);
|
||||||
* everything is verified correctly out but one or more public keys
|
|
||||||
* are not accepted. This includes the case where integrity data is
|
/* Performs a full verification of the slot identified by |ab_suffix|
|
||||||
* not signed.
|
* and load and verify the contents of the partitions whose name is in
|
||||||
*
|
* the NULL-terminated string array |requested_partitions| (each
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_OOM is returned if unable to
|
* partition must use hash verification). If not using A/B, pass an
|
||||||
* allocate memory.
|
* empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
|
||||||
*
|
* must include the leading underscore, for example "_a" should be
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_IO is returned if an I/O error
|
* used to refer to the first slot.
|
||||||
* occurred while trying to load data or get a rollback index.
|
*
|
||||||
*
|
* Typically the |requested_partitions| array only contains a single
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION is returned if the data
|
* item for the boot partition, 'boot'.
|
||||||
* did not verify, e.g. the digest didn't match or signature checks
|
*
|
||||||
* failed.
|
* Verification includes loading and verifying data from the 'vbmeta',
|
||||||
*
|
* the requested hash partitions, and possibly other partitions (with
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned if a
|
* |ab_suffix| appended), inspecting rollback indexes, and checking if
|
||||||
* rollback index was less than its stored value.
|
* the public key used to sign the data is acceptable. The functions
|
||||||
*
|
* in |ops| will be used to do this.
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned if some
|
*
|
||||||
* of the metadata is invalid or inconsistent.
|
* If |out_data| is not NULL, it will be set to a newly allocated
|
||||||
*
|
* |AvbSlotVerifyData| struct containing all the data needed to
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
|
* actually boot the slot. This data structure should be freed with
|
||||||
* some of the metadata requires a newer version of libavb than what
|
* avb_slot_verify_data_free() when you are done with it. See below
|
||||||
* is in use.
|
* for when this is returned.
|
||||||
*
|
*
|
||||||
* AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
|
* The |flags| parameter is used to influence the semantics of
|
||||||
* caller passed invalid parameters, for example trying to use
|
* avb_slot_verify() - for example the
|
||||||
* AVB_HASHTREE_ERROR_MODE_LOGGING without
|
* AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
|
||||||
* AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
|
* ignore verification errors which is something needed in the
|
||||||
*/
|
* UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
|
||||||
AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
|
*
|
||||||
const char* const* requested_partitions,
|
* The |hashtree_error_mode| parameter should be set to the desired error
|
||||||
const char* ab_suffix,
|
* handling mode. See the AvbHashtreeErrorMode enumeration for details.
|
||||||
AvbSlotVerifyFlags flags,
|
*
|
||||||
AvbHashtreeErrorMode hashtree_error_mode,
|
* Also note that |out_data| is never set if
|
||||||
AvbSlotVerifyData** out_data);
|
* AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
|
||||||
|
* or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
|
||||||
#ifdef __cplusplus
|
*
|
||||||
}
|
* AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
|
||||||
#endif
|
* correctly and all public keys are accepted.
|
||||||
|
*
|
||||||
#endif /* AVB_SLOT_VERIFY_H_ */
|
* 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_ */
|
||||||
|
|
|
||||||
|
|
@ -1,130 +1,138 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
|
||||||
#error "Never include this file directly, include libavb.h instead."
|
#error "Never include this file directly, include libavb.h instead."
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVB_SYSDEPS_H_
|
#ifndef AVB_SYSDEPS_H_
|
||||||
#define AVB_SYSDEPS_H_
|
#define AVB_SYSDEPS_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Change these includes to match your platform to bring in the
|
/* Change these includes to match your platform to bring in the
|
||||||
* equivalent types available in a normal C runtime. At least things
|
* equivalent types available in a normal C runtime. At least things
|
||||||
* like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
|
* like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
|
||||||
* must be present.
|
* must be present.
|
||||||
*/
|
*/
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#ifdef CONFIG_USE_STDINT
|
#ifdef CONFIG_USE_STDINT
|
||||||
/* Provided by gcc. */
|
/* Provided by gcc. */
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#else
|
#else
|
||||||
/* Type for `void *' pointers. */
|
/* Type for `void *' pointers. */
|
||||||
typedef unsigned long int uintptr_t;
|
typedef unsigned long int uintptr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If you don't have gcc or clang, these attribute macros may need to
|
/* If you don't have gcc or clang, these attribute macros may need to
|
||||||
* be adjusted.
|
* be adjusted.
|
||||||
*/
|
*/
|
||||||
#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||||
#define AVB_ATTR_PACKED __attribute__((packed))
|
#define AVB_ATTR_PACKED __attribute__((packed))
|
||||||
#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
|
#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
|
||||||
#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
|
#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
|
||||||
|
|
||||||
/* Size in bytes used for alignment. */
|
/* Size in bytes used for alignment. */
|
||||||
#ifdef __LP64__
|
#ifdef __LP64__
|
||||||
#define AVB_ALIGNMENT_SIZE 8
|
#define AVB_ALIGNMENT_SIZE 8
|
||||||
#else
|
#else
|
||||||
#define AVB_ALIGNMENT_SIZE 4
|
#define AVB_ALIGNMENT_SIZE 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Compare |n| bytes in |src1| and |src2|.
|
/* Compare |n| bytes in |src1| and |src2|.
|
||||||
*
|
*
|
||||||
* Returns an integer less than, equal to, or greater than zero if the
|
* 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,
|
* first |n| bytes of |src1| is found, respectively, to be less than,
|
||||||
* to match, or be greater than the first |n| bytes of |src2|. */
|
* to match, or be greater than the first |n| bytes of |src2|. */
|
||||||
int avb_memcmp(const void* src1,
|
int avb_memcmp(const void* src1,
|
||||||
const void* src2,
|
const void* src2,
|
||||||
size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
|
size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Compare two strings.
|
/* Compare two strings.
|
||||||
*
|
*
|
||||||
* Return an integer less than, equal to, or greater than zero if |s1|
|
* 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
|
* is found, respectively, to be less than, to match, or be greater
|
||||||
* than |s2|.
|
* than |s2|.
|
||||||
*/
|
*/
|
||||||
int avb_strcmp(const char* s1, const char* s2);
|
int avb_strcmp(const char* s1, const char* s2);
|
||||||
|
|
||||||
/* Copy |n| bytes from |src| to |dest|. */
|
/* Compare |n| bytes in two strings.
|
||||||
void* avb_memcpy(void* dest, const void* src, size_t n);
|
*
|
||||||
|
* Return an integer less than, equal to, or greater than zero if the
|
||||||
/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */
|
* first |n| bytes of |s1| is found, respectively, to be less than,
|
||||||
void* avb_memset(void* dest, const int c, size_t n);
|
* to match, or be greater than the first |n| bytes of |s2|.
|
||||||
|
*/
|
||||||
/* Prints out a message. The string passed must be a NUL-terminated
|
int avb_strncmp(const char* s1, const char* s2, size_t n);
|
||||||
* UTF-8 string.
|
|
||||||
*/
|
/* Copy |n| bytes from |src| to |dest|. */
|
||||||
void avb_print(const char* message);
|
void* avb_memcpy(void* dest, const void* src, size_t n);
|
||||||
|
|
||||||
/* Prints out a vector of strings. Each argument must point to a
|
/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */
|
||||||
* NUL-terminated UTF-8 string and NULL should be the last argument.
|
void* avb_memset(void* dest, const int c, size_t n);
|
||||||
*/
|
|
||||||
void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
|
/* Prints out a message. The string passed must be a NUL-terminated
|
||||||
|
* UTF-8 string.
|
||||||
/* Aborts the program or reboots the device. */
|
*/
|
||||||
void avb_abort(void);
|
void avb_print(const char* message);
|
||||||
|
|
||||||
/* Allocates |size| bytes. Returns NULL if no memory is available,
|
/* Prints out a vector of strings. Each argument must point to a
|
||||||
* otherwise a pointer to the allocated memory.
|
* NUL-terminated UTF-8 string and NULL should be the last argument.
|
||||||
*
|
*/
|
||||||
* The memory is not initialized.
|
void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
|
||||||
*
|
|
||||||
* The pointer returned is guaranteed to be word-aligned.
|
/* Aborts the program or reboots the device. */
|
||||||
*
|
void avb_abort(void);
|
||||||
* The memory should be freed with avb_free() when you are done with it.
|
|
||||||
*/
|
/* Allocates |size| bytes. Returns NULL if no memory is available,
|
||||||
void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
|
* otherwise a pointer to the allocated memory.
|
||||||
|
*
|
||||||
/* Frees memory previously allocated with avb_malloc(). */
|
* The memory is not initialized.
|
||||||
void avb_free(void* ptr);
|
*
|
||||||
|
* The pointer returned is guaranteed to be word-aligned.
|
||||||
/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
|
*
|
||||||
size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
|
* The memory should be freed with avb_free() when you are done with it.
|
||||||
|
*/
|
||||||
/* Divide the |dividend| by 10 and saves back to the pointer. Return the
|
void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||||
* remainder. */
|
|
||||||
uint32_t avb_div_by_10(uint64_t* dividend);
|
/* Frees memory previously allocated with avb_malloc(). */
|
||||||
|
void avb_free(void* ptr);
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
|
||||||
#endif
|
size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
#endif /* AVB_SYSDEPS_H_ */
|
/* 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_ */
|
||||||
|
|
|
||||||
|
|
@ -1,440 +1,474 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <android_avb/avb_cmdline.h>
|
#include <android_avb/avb_cmdline.h>
|
||||||
#include <android_avb/avb_sha.h>
|
#include <android_avb/avb_sha.h>
|
||||||
#include <android_avb/avb_util.h>
|
#include <android_avb/avb_util.h>
|
||||||
#include <android_avb/avb_version.h>
|
#include <android_avb/avb_version.h>
|
||||||
|
|
||||||
#define NUM_GUIDS 3
|
#define NUM_GUIDS 3
|
||||||
|
|
||||||
/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
|
/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
|
||||||
* values. Returns NULL on OOM, otherwise the cmdline with values
|
* values. Returns NULL on OOM, otherwise the cmdline with values
|
||||||
* replaced.
|
* replaced.
|
||||||
*/
|
*/
|
||||||
char* avb_sub_cmdline(AvbOps* ops,
|
char* avb_sub_cmdline(AvbOps* ops,
|
||||||
const char* cmdline,
|
const char* cmdline,
|
||||||
const char* ab_suffix,
|
const char* ab_suffix,
|
||||||
bool using_boot_for_vbmeta,
|
bool using_boot_for_vbmeta,
|
||||||
const AvbCmdlineSubstList* additional_substitutions) {
|
const AvbCmdlineSubstList* additional_substitutions) {
|
||||||
const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
|
const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
|
||||||
const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
|
const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
|
||||||
"$(ANDROID_BOOT_PARTUUID)",
|
"$(ANDROID_BOOT_PARTUUID)",
|
||||||
"$(ANDROID_VBMETA_PARTUUID)"};
|
"$(ANDROID_VBMETA_PARTUUID)"};
|
||||||
char* ret = NULL;
|
char* ret = NULL;
|
||||||
AvbIOResult io_ret;
|
AvbIOResult io_ret;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
/* Special-case for when the top-level vbmeta struct is in the boot
|
/* Special-case for when the top-level vbmeta struct is in the boot
|
||||||
* partition.
|
* partition.
|
||||||
*/
|
*/
|
||||||
if (using_boot_for_vbmeta) {
|
if (using_boot_for_vbmeta) {
|
||||||
part_name_str[2] = "boot";
|
part_name_str[2] = "boot";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace unique partition GUIDs */
|
/* Replace unique partition GUIDs */
|
||||||
for (n = 0; n < NUM_GUIDS; n++) {
|
for (n = 0; n < NUM_GUIDS; n++) {
|
||||||
char part_name[AVB_PART_NAME_MAX_SIZE];
|
char part_name[AVB_PART_NAME_MAX_SIZE];
|
||||||
char guid_buf[37];
|
char guid_buf[37];
|
||||||
|
|
||||||
if (!avb_str_concat(part_name,
|
/* Don't attempt to query the partition guid unless its search string is
|
||||||
sizeof part_name,
|
* present in the command line. Note: the original cmdline is used here,
|
||||||
part_name_str[n],
|
* not the replaced one. See b/116010959.
|
||||||
avb_strlen(part_name_str[n]),
|
*/
|
||||||
ab_suffix,
|
if (avb_strstr(cmdline, replace_str[n]) == NULL) {
|
||||||
avb_strlen(ab_suffix))) {
|
continue;
|
||||||
avb_error("Partition name and suffix does not fit.\n");
|
}
|
||||||
goto fail;
|
|
||||||
}
|
if (!avb_str_concat(part_name,
|
||||||
|
sizeof part_name,
|
||||||
io_ret = ops->get_unique_guid_for_partition(
|
part_name_str[n],
|
||||||
ops, part_name, guid_buf, sizeof guid_buf);
|
avb_strlen(part_name_str[n]),
|
||||||
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
|
ab_suffix,
|
||||||
goto fail;
|
avb_strlen(ab_suffix))) {
|
||||||
} else if (io_ret != AVB_IO_RESULT_OK) {
|
avb_error("Partition name and suffix does not fit.\n");
|
||||||
avb_error("Error getting unique GUID for partition.\n");
|
goto fail;
|
||||||
goto fail;
|
}
|
||||||
}
|
|
||||||
|
io_ret = ops->get_unique_guid_for_partition(
|
||||||
if (ret == NULL) {
|
ops, part_name, guid_buf, sizeof guid_buf);
|
||||||
ret = avb_replace(cmdline, replace_str[n], guid_buf);
|
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
|
||||||
} else {
|
goto fail;
|
||||||
char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
|
} else if (io_ret != AVB_IO_RESULT_OK) {
|
||||||
avb_free(ret);
|
avb_error("Error getting unique GUID for partition.\n");
|
||||||
ret = new_ret;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (ret == NULL) {
|
|
||||||
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_assert(ret != NULL);
|
avb_free(ret);
|
||||||
|
ret = new_ret;
|
||||||
/* Replace any additional substitutions. */
|
}
|
||||||
if (additional_substitutions != NULL) {
|
if (ret == NULL) {
|
||||||
for (n = 0; n < additional_substitutions->size; ++n) {
|
goto fail;
|
||||||
char* new_ret = avb_replace(ret,
|
}
|
||||||
additional_substitutions->tokens[n],
|
}
|
||||||
additional_substitutions->values[n]);
|
|
||||||
avb_free(ret);
|
/* It's possible there is no _PARTUUID for replacement above.
|
||||||
ret = new_ret;
|
* Duplicate cmdline to ret for additional substitutions below.
|
||||||
if (ret == NULL) {
|
*/
|
||||||
goto fail;
|
if (ret == NULL) {
|
||||||
}
|
ret = avb_strdup(cmdline);
|
||||||
}
|
if (ret == NULL) {
|
||||||
}
|
goto fail;
|
||||||
|
}
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
fail:
|
/* Replace any additional substitutions. */
|
||||||
if (ret != NULL) {
|
if (additional_substitutions != NULL) {
|
||||||
avb_free(ret);
|
for (n = 0; n < additional_substitutions->size; ++n) {
|
||||||
}
|
char* new_ret = avb_replace(ret,
|
||||||
return NULL;
|
additional_substitutions->tokens[n],
|
||||||
}
|
additional_substitutions->values[n]);
|
||||||
|
avb_free(ret);
|
||||||
static int cmdline_append_option(AvbSlotVerifyData* slot_data,
|
ret = new_ret;
|
||||||
const char* key,
|
if (ret == NULL) {
|
||||||
const char* value) {
|
goto fail;
|
||||||
size_t offset, key_len, value_len;
|
}
|
||||||
char* new_cmdline;
|
}
|
||||||
|
}
|
||||||
key_len = avb_strlen(key);
|
|
||||||
value_len = avb_strlen(value);
|
return ret;
|
||||||
|
|
||||||
offset = 0;
|
fail:
|
||||||
if (slot_data->cmdline != NULL) {
|
if (ret != NULL) {
|
||||||
offset = avb_strlen(slot_data->cmdline);
|
avb_free(ret);
|
||||||
if (offset > 0) {
|
}
|
||||||
offset += 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
static int cmdline_append_option(AvbSlotVerifyData* slot_data,
|
||||||
new_cmdline = avb_calloc(offset + key_len + value_len + 2);
|
const char* key,
|
||||||
if (new_cmdline == NULL) {
|
const char* value) {
|
||||||
return 0;
|
size_t offset, key_len, value_len;
|
||||||
}
|
char* new_cmdline;
|
||||||
if (offset > 0) {
|
|
||||||
avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
|
key_len = avb_strlen(key);
|
||||||
new_cmdline[offset - 1] = ' ';
|
value_len = avb_strlen(value);
|
||||||
}
|
|
||||||
avb_memcpy(new_cmdline + offset, key, key_len);
|
offset = 0;
|
||||||
new_cmdline[offset + key_len] = '=';
|
if (slot_data->cmdline != NULL) {
|
||||||
avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
|
offset = avb_strlen(slot_data->cmdline);
|
||||||
if (slot_data->cmdline != NULL) {
|
if (offset > 0) {
|
||||||
avb_free(slot_data->cmdline);
|
offset += 1;
|
||||||
}
|
}
|
||||||
slot_data->cmdline = new_cmdline;
|
}
|
||||||
|
|
||||||
return 1;
|
new_cmdline = avb_calloc(offset + key_len + value_len + 2);
|
||||||
}
|
if (new_cmdline == NULL) {
|
||||||
|
return 0;
|
||||||
#define AVB_MAX_DIGITS_UINT64 32
|
}
|
||||||
|
if (offset > 0) {
|
||||||
/* Writes |value| to |digits| in base 10 followed by a NUL byte.
|
avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
|
||||||
* Returns number of characters written excluding the NUL byte.
|
new_cmdline[offset - 1] = ' ';
|
||||||
*/
|
}
|
||||||
static size_t uint64_to_base10(uint64_t value,
|
avb_memcpy(new_cmdline + offset, key, key_len);
|
||||||
char digits[AVB_MAX_DIGITS_UINT64]) {
|
new_cmdline[offset + key_len] = '=';
|
||||||
char rev_digits[AVB_MAX_DIGITS_UINT64];
|
avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
|
||||||
size_t n, num_digits;
|
if (slot_data->cmdline != NULL) {
|
||||||
|
avb_free(slot_data->cmdline);
|
||||||
for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
|
}
|
||||||
rev_digits[num_digits++] = avb_div_by_10(&value) + '0';
|
slot_data->cmdline = new_cmdline;
|
||||||
if (value == 0) {
|
|
||||||
break;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#define AVB_MAX_DIGITS_UINT64 32
|
||||||
for (n = 0; n < num_digits; n++) {
|
|
||||||
digits[n] = rev_digits[num_digits - 1 - n];
|
/* Writes |value| to |digits| in base 10 followed by a NUL byte.
|
||||||
}
|
* Returns number of characters written excluding the NUL byte.
|
||||||
digits[n] = '\0';
|
*/
|
||||||
return n;
|
static size_t uint64_to_base10(uint64_t value,
|
||||||
}
|
char digits[AVB_MAX_DIGITS_UINT64]) {
|
||||||
|
char rev_digits[AVB_MAX_DIGITS_UINT64];
|
||||||
static int cmdline_append_version(AvbSlotVerifyData* slot_data,
|
size_t n, num_digits;
|
||||||
const char* key,
|
|
||||||
uint64_t major_version,
|
for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
|
||||||
uint64_t minor_version) {
|
rev_digits[num_digits++] = avb_div_by_10(&value) + '0';
|
||||||
char major_digits[AVB_MAX_DIGITS_UINT64];
|
if (value == 0) {
|
||||||
char minor_digits[AVB_MAX_DIGITS_UINT64];
|
break;
|
||||||
char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
|
}
|
||||||
size_t num_major_digits, num_minor_digits;
|
}
|
||||||
|
|
||||||
num_major_digits = uint64_to_base10(major_version, major_digits);
|
for (n = 0; n < num_digits; n++) {
|
||||||
num_minor_digits = uint64_to_base10(minor_version, minor_digits);
|
digits[n] = rev_digits[num_digits - 1 - n];
|
||||||
avb_memcpy(combined, major_digits, num_major_digits);
|
}
|
||||||
combined[num_major_digits] = '.';
|
digits[n] = '\0';
|
||||||
avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
|
return n;
|
||||||
combined[num_major_digits + 1 + num_minor_digits] = '\0';
|
}
|
||||||
|
|
||||||
return cmdline_append_option(slot_data, key, combined);
|
static int cmdline_append_version(AvbSlotVerifyData* slot_data,
|
||||||
}
|
const char* key,
|
||||||
|
uint64_t major_version,
|
||||||
static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
|
uint64_t minor_version) {
|
||||||
const char* key,
|
char major_digits[AVB_MAX_DIGITS_UINT64];
|
||||||
uint64_t value) {
|
char minor_digits[AVB_MAX_DIGITS_UINT64];
|
||||||
char digits[AVB_MAX_DIGITS_UINT64];
|
char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
|
||||||
uint64_to_base10(value, digits);
|
size_t num_major_digits, num_minor_digits;
|
||||||
return cmdline_append_option(slot_data, key, digits);
|
|
||||||
}
|
num_major_digits = uint64_to_base10(major_version, major_digits);
|
||||||
|
num_minor_digits = uint64_to_base10(minor_version, minor_digits);
|
||||||
static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
|
avb_memcpy(combined, major_digits, num_major_digits);
|
||||||
const char* key,
|
combined[num_major_digits] = '.';
|
||||||
const uint8_t* data,
|
avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
|
||||||
size_t data_len) {
|
combined[num_major_digits + 1 + num_minor_digits] = '\0';
|
||||||
int ret;
|
|
||||||
char* hex_data = avb_bin2hex(data, data_len);
|
return cmdline_append_option(slot_data, key, combined);
|
||||||
if (hex_data == NULL) {
|
}
|
||||||
return 0;
|
|
||||||
}
|
static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
|
||||||
ret = cmdline_append_option(slot_data, key, hex_data);
|
const char* key,
|
||||||
avb_free(hex_data);
|
uint64_t value) {
|
||||||
return ret;
|
char digits[AVB_MAX_DIGITS_UINT64];
|
||||||
}
|
uint64_to_base10(value, digits);
|
||||||
|
return cmdline_append_option(slot_data, key, digits);
|
||||||
AvbSlotVerifyResult avb_append_options(
|
}
|
||||||
AvbOps* ops,
|
|
||||||
AvbSlotVerifyData* slot_data,
|
static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
|
||||||
AvbVBMetaImageHeader* toplevel_vbmeta,
|
const char* key,
|
||||||
AvbAlgorithmType algorithm_type,
|
const uint8_t* data,
|
||||||
AvbHashtreeErrorMode hashtree_error_mode) {
|
size_t data_len) {
|
||||||
AvbSlotVerifyResult ret;
|
int ret;
|
||||||
const char* verity_mode = NULL;
|
char* hex_data = avb_bin2hex(data, data_len);
|
||||||
bool is_device_unlocked;
|
if (hex_data == NULL) {
|
||||||
AvbIOResult io_ret;
|
return 0;
|
||||||
|
}
|
||||||
/* Add androidboot.vbmeta.device option. */
|
ret = cmdline_append_option(slot_data, key, hex_data);
|
||||||
if (!cmdline_append_option(slot_data,
|
avb_free(hex_data);
|
||||||
"androidboot.vbmeta.device",
|
return ret;
|
||||||
"PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
|
}
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
|
||||||
goto out;
|
AvbSlotVerifyResult avb_append_options(
|
||||||
}
|
AvbOps* ops,
|
||||||
|
AvbSlotVerifyFlags flags,
|
||||||
/* Add androidboot.vbmeta.avb_version option. */
|
AvbSlotVerifyData* slot_data,
|
||||||
if (!cmdline_append_version(slot_data,
|
AvbVBMetaImageHeader* toplevel_vbmeta,
|
||||||
"androidboot.vbmeta.avb_version",
|
AvbAlgorithmType algorithm_type,
|
||||||
AVB_VERSION_MAJOR,
|
AvbHashtreeErrorMode hashtree_error_mode,
|
||||||
AVB_VERSION_MINOR)) {
|
AvbHashtreeErrorMode resolved_hashtree_error_mode) {
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
AvbSlotVerifyResult ret;
|
||||||
goto out;
|
const char* verity_mode = NULL;
|
||||||
}
|
bool is_device_unlocked;
|
||||||
|
AvbIOResult io_ret;
|
||||||
/* Set androidboot.avb.device_state to "locked" or "unlocked". */
|
|
||||||
io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
|
/* Add androidboot.vbmeta.device option... except if not using a vbmeta
|
||||||
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
|
* partition since it doesn't make sense in that case.
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
*/
|
||||||
goto out;
|
if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
|
||||||
} else if (io_ret != AVB_IO_RESULT_OK) {
|
if (!cmdline_append_option(slot_data,
|
||||||
avb_error("Error getting device state.\n");
|
"androidboot.vbmeta.device",
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
|
"PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
|
||||||
goto out;
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
}
|
goto out;
|
||||||
if (!cmdline_append_option(slot_data,
|
}
|
||||||
"androidboot.vbmeta.device_state",
|
}
|
||||||
is_device_unlocked ? "unlocked" : "locked")) {
|
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
/* Add androidboot.vbmeta.avb_version option. */
|
||||||
goto out;
|
if (!cmdline_append_version(slot_data,
|
||||||
}
|
"androidboot.vbmeta.avb_version",
|
||||||
|
AVB_VERSION_MAJOR,
|
||||||
/* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
|
AVB_VERSION_MINOR)) {
|
||||||
* function as is used to sign vbmeta.
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
*/
|
goto out;
|
||||||
switch (algorithm_type) {
|
}
|
||||||
/* Explicit fallthrough. */
|
|
||||||
case AVB_ALGORITHM_TYPE_NONE:
|
/* Set androidboot.avb.device_state to "locked" or "unlocked". */
|
||||||
case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
|
io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
|
||||||
case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
|
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
|
||||||
case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
size_t n, total_size = 0;
|
goto out;
|
||||||
uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
|
} else if (io_ret != AVB_IO_RESULT_OK) {
|
||||||
avb_slot_verify_data_calculate_vbmeta_digest(
|
avb_error("Error getting device state.\n");
|
||||||
slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
|
||||||
for (n = 0; n < slot_data->num_vbmeta_images; n++) {
|
goto out;
|
||||||
total_size += slot_data->vbmeta_images[n].vbmeta_size;
|
}
|
||||||
}
|
if (!cmdline_append_option(slot_data,
|
||||||
if (!cmdline_append_option(
|
"androidboot.vbmeta.device_state",
|
||||||
slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
|
is_device_unlocked ? "unlocked" : "locked")) {
|
||||||
!cmdline_append_uint64_base10(
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
slot_data, "androidboot.vbmeta.size", total_size) ||
|
goto out;
|
||||||
!cmdline_append_hex(slot_data,
|
}
|
||||||
"androidboot.vbmeta.digest",
|
|
||||||
vbmeta_digest,
|
/* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
|
||||||
AVB_SHA256_DIGEST_SIZE)) {
|
* function as is used to sign vbmeta.
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
*/
|
||||||
goto out;
|
switch (algorithm_type) {
|
||||||
}
|
/* Explicit fallthrough. */
|
||||||
} break;
|
case AVB_ALGORITHM_TYPE_NONE:
|
||||||
/* Explicit fallthrough. */
|
case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
|
||||||
case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
|
case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
|
||||||
case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
|
case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
|
||||||
case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
|
size_t n, total_size = 0;
|
||||||
size_t n, total_size = 0;
|
uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
|
||||||
uint8_t vbmeta_digest[AVB_SHA512_DIGEST_SIZE];
|
avb_slot_verify_data_calculate_vbmeta_digest(
|
||||||
avb_slot_verify_data_calculate_vbmeta_digest(
|
slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
|
||||||
slot_data, AVB_DIGEST_TYPE_SHA512, vbmeta_digest);
|
for (n = 0; n < slot_data->num_vbmeta_images; n++) {
|
||||||
for (n = 0; n < slot_data->num_vbmeta_images; n++) {
|
total_size += slot_data->vbmeta_images[n].vbmeta_size;
|
||||||
total_size += slot_data->vbmeta_images[n].vbmeta_size;
|
}
|
||||||
}
|
if (!cmdline_append_option(
|
||||||
if (!cmdline_append_option(
|
slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
|
||||||
slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
|
!cmdline_append_uint64_base10(
|
||||||
!cmdline_append_uint64_base10(
|
slot_data, "androidboot.vbmeta.size", total_size) ||
|
||||||
slot_data, "androidboot.vbmeta.size", total_size) ||
|
!cmdline_append_hex(slot_data,
|
||||||
!cmdline_append_hex(slot_data,
|
"androidboot.vbmeta.digest",
|
||||||
"androidboot.vbmeta.digest",
|
vbmeta_digest,
|
||||||
vbmeta_digest,
|
AVB_SHA256_DIGEST_SIZE)) {
|
||||||
AVB_SHA512_DIGEST_SIZE)) {
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
goto out;
|
||||||
goto out;
|
}
|
||||||
}
|
} break;
|
||||||
} break;
|
/* Explicit fallthrough. */
|
||||||
case _AVB_ALGORITHM_NUM_TYPES:
|
case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
|
||||||
avb_assert_not_reached();
|
case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
|
||||||
break;
|
case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
|
||||||
}
|
size_t n, total_size = 0;
|
||||||
|
uint8_t vbmeta_digest[AVB_SHA512_DIGEST_SIZE];
|
||||||
/* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
|
avb_slot_verify_data_calculate_vbmeta_digest(
|
||||||
if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
|
slot_data, AVB_DIGEST_TYPE_SHA512, vbmeta_digest);
|
||||||
verity_mode = "disabled";
|
for (n = 0; n < slot_data->num_vbmeta_images; n++) {
|
||||||
} else {
|
total_size += slot_data->vbmeta_images[n].vbmeta_size;
|
||||||
const char* dm_verity_mode = NULL;
|
}
|
||||||
char* new_ret;
|
if (!cmdline_append_option(
|
||||||
|
slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
|
||||||
switch (hashtree_error_mode) {
|
!cmdline_append_uint64_base10(
|
||||||
case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
|
slot_data, "androidboot.vbmeta.size", total_size) ||
|
||||||
if (!cmdline_append_option(
|
!cmdline_append_hex(slot_data,
|
||||||
slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
|
"androidboot.vbmeta.digest",
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
vbmeta_digest,
|
||||||
goto out;
|
AVB_SHA512_DIGEST_SIZE)) {
|
||||||
}
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
verity_mode = "enforcing";
|
goto out;
|
||||||
dm_verity_mode = "restart_on_corruption";
|
}
|
||||||
break;
|
} break;
|
||||||
case AVB_HASHTREE_ERROR_MODE_RESTART:
|
case _AVB_ALGORITHM_NUM_TYPES:
|
||||||
verity_mode = "enforcing";
|
avb_assert_not_reached();
|
||||||
dm_verity_mode = "restart_on_corruption";
|
break;
|
||||||
break;
|
}
|
||||||
case AVB_HASHTREE_ERROR_MODE_EIO:
|
|
||||||
verity_mode = "eio";
|
/* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
|
||||||
/* For now there's no option to specify the EIO mode. So
|
if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
|
||||||
* just use 'ignore_zero_blocks' since that's already set
|
verity_mode = "disabled";
|
||||||
* and dm-verity-target.c supports specifying this multiple
|
} else {
|
||||||
* times.
|
const char* dm_verity_mode = NULL;
|
||||||
*/
|
char* new_ret;
|
||||||
dm_verity_mode = "ignore_zero_blocks";
|
|
||||||
break;
|
switch (resolved_hashtree_error_mode) {
|
||||||
case AVB_HASHTREE_ERROR_MODE_LOGGING:
|
case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
|
||||||
verity_mode = "logging";
|
if (!cmdline_append_option(
|
||||||
dm_verity_mode = "ignore_corruption";
|
slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
|
||||||
break;
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
}
|
goto out;
|
||||||
new_ret = avb_replace(
|
}
|
||||||
slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
|
verity_mode = "enforcing";
|
||||||
avb_free(slot_data->cmdline);
|
dm_verity_mode = "restart_on_corruption";
|
||||||
slot_data->cmdline = new_ret;
|
break;
|
||||||
if (slot_data->cmdline == NULL) {
|
case AVB_HASHTREE_ERROR_MODE_RESTART:
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
verity_mode = "enforcing";
|
||||||
goto out;
|
dm_verity_mode = "restart_on_corruption";
|
||||||
}
|
break;
|
||||||
}
|
case AVB_HASHTREE_ERROR_MODE_EIO:
|
||||||
if (!cmdline_append_option(
|
verity_mode = "eio";
|
||||||
slot_data, "androidboot.veritymode", verity_mode)) {
|
/* For now there's no option to specify the EIO mode. So
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
* just use 'ignore_zero_blocks' since that's already set
|
||||||
goto out;
|
* and dm-verity-target.c supports specifying this multiple
|
||||||
}
|
* times.
|
||||||
|
*/
|
||||||
ret = AVB_SLOT_VERIFY_RESULT_OK;
|
dm_verity_mode = "ignore_zero_blocks";
|
||||||
|
break;
|
||||||
out:
|
case AVB_HASHTREE_ERROR_MODE_LOGGING:
|
||||||
|
verity_mode = "logging";
|
||||||
return ret;
|
dm_verity_mode = "ignore_corruption";
|
||||||
}
|
break;
|
||||||
|
case AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO:
|
||||||
AvbCmdlineSubstList* avb_new_cmdline_subst_list() {
|
// Should never get here because MANAGED_RESTART_AND_EIO is
|
||||||
return (AvbCmdlineSubstList*)avb_calloc(sizeof(AvbCmdlineSubstList));
|
// remapped by avb_manage_hashtree_error_mode().
|
||||||
}
|
avb_assert_not_reached();
|
||||||
|
break;
|
||||||
void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst) {
|
}
|
||||||
size_t i;
|
new_ret = avb_replace(
|
||||||
for (i = 0; i < cmdline_subst->size; ++i) {
|
slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
|
||||||
avb_free(cmdline_subst->tokens[i]);
|
avb_free(slot_data->cmdline);
|
||||||
avb_free(cmdline_subst->values[i]);
|
slot_data->cmdline = new_ret;
|
||||||
}
|
if (slot_data->cmdline == NULL) {
|
||||||
cmdline_subst->size = 0;
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
avb_free(cmdline_subst);
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
AvbSlotVerifyResult avb_add_root_digest_substitution(
|
if (!cmdline_append_option(
|
||||||
const char* part_name,
|
slot_data, "androidboot.veritymode", verity_mode)) {
|
||||||
const uint8_t* digest,
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
size_t digest_size,
|
goto out;
|
||||||
AvbCmdlineSubstList* out_cmdline_subst) {
|
}
|
||||||
const char* kDigestSubPrefix = "$(AVB_";
|
if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
|
||||||
const char* kDigestSubSuffix = "_ROOT_DIGEST)";
|
if (!cmdline_append_option(
|
||||||
size_t part_name_len = avb_strlen(part_name);
|
slot_data, "androidboot.veritymode.managed", "yes")) {
|
||||||
size_t list_index = out_cmdline_subst->size;
|
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
||||||
|
goto out;
|
||||||
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) {
|
ret = AVB_SLOT_VERIFY_RESULT_OK;
|
||||||
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
|
|
||||||
}
|
out:
|
||||||
|
|
||||||
if (out_cmdline_subst->size >= AVB_MAX_NUM_CMDLINE_SUBST) {
|
return ret;
|
||||||
/* The list is full. Currently dynamic growth of this list is not supported.
|
}
|
||||||
*/
|
|
||||||
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
|
AvbCmdlineSubstList* avb_new_cmdline_subst_list() {
|
||||||
}
|
return (AvbCmdlineSubstList*)avb_calloc(sizeof(AvbCmdlineSubstList));
|
||||||
|
}
|
||||||
/* Construct the token to replace in the command line based on the partition
|
|
||||||
* name. For partition 'foo', this will be '$(AVB_FOO_ROOT_DIGEST)'.
|
void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst) {
|
||||||
*/
|
size_t i;
|
||||||
out_cmdline_subst->tokens[list_index] =
|
for (i = 0; i < cmdline_subst->size; ++i) {
|
||||||
avb_strdupv(kDigestSubPrefix, part_name, kDigestSubSuffix, NULL);
|
avb_free(cmdline_subst->tokens[i]);
|
||||||
if (out_cmdline_subst->tokens[list_index] == NULL) {
|
avb_free(cmdline_subst->values[i]);
|
||||||
goto fail;
|
}
|
||||||
}
|
cmdline_subst->size = 0;
|
||||||
avb_uppercase(out_cmdline_subst->tokens[list_index]);
|
avb_free(cmdline_subst);
|
||||||
|
}
|
||||||
/* The digest value is hex encoded when inserted in the command line. */
|
|
||||||
out_cmdline_subst->values[list_index] = avb_bin2hex(digest, digest_size);
|
AvbSlotVerifyResult avb_add_root_digest_substitution(
|
||||||
if (out_cmdline_subst->values[list_index] == NULL) {
|
const char* part_name,
|
||||||
goto fail;
|
const uint8_t* digest,
|
||||||
}
|
size_t digest_size,
|
||||||
|
AvbCmdlineSubstList* out_cmdline_subst) {
|
||||||
out_cmdline_subst->size++;
|
const char* kDigestSubPrefix = "$(AVB_";
|
||||||
return AVB_SLOT_VERIFY_RESULT_OK;
|
const char* kDigestSubSuffix = "_ROOT_DIGEST)";
|
||||||
|
size_t part_name_len = avb_strlen(part_name);
|
||||||
fail:
|
size_t list_index = out_cmdline_subst->size;
|
||||||
if (out_cmdline_subst->tokens[list_index]) {
|
|
||||||
avb_free(out_cmdline_subst->tokens[list_index]);
|
avb_assert(part_name_len < AVB_PART_NAME_MAX_SIZE);
|
||||||
}
|
avb_assert(digest_size <= AVB_SHA512_DIGEST_SIZE);
|
||||||
if (out_cmdline_subst->values[list_index]) {
|
if (part_name_len >= AVB_PART_NAME_MAX_SIZE ||
|
||||||
avb_free(out_cmdline_subst->values[list_index]);
|
digest_size > AVB_SHA512_DIGEST_SIZE) {
|
||||||
}
|
return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
|
||||||
return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
|
}
|
||||||
}
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,160 +1,167 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <android_avb/avb_descriptor.h>
|
#include <android_avb/avb_descriptor.h>
|
||||||
#include <android_avb/avb_util.h>
|
#include <android_avb/avb_util.h>
|
||||||
#include <android_avb/avb_vbmeta_image.h>
|
#include <android_avb/avb_vbmeta_image.h>
|
||||||
|
|
||||||
bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
|
bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
|
||||||
AvbDescriptor* dest) {
|
AvbDescriptor* dest) {
|
||||||
dest->tag = avb_be64toh(src->tag);
|
dest->tag = avb_be64toh(src->tag);
|
||||||
dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
|
dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
|
||||||
|
|
||||||
if ((dest->num_bytes_following & 0x07) != 0) {
|
if ((dest->num_bytes_following & 0x07) != 0) {
|
||||||
avb_error("Descriptor size is not divisible by 8.\n");
|
avb_error("Descriptor size is not divisible by 8.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool avb_descriptor_foreach(const uint8_t* image_data,
|
bool avb_descriptor_foreach(const uint8_t* image_data,
|
||||||
size_t image_size,
|
size_t image_size,
|
||||||
AvbDescriptorForeachFunc foreach_func,
|
AvbDescriptorForeachFunc foreach_func,
|
||||||
void* user_data) {
|
void* user_data) {
|
||||||
const AvbVBMetaImageHeader* header = NULL;
|
const AvbVBMetaImageHeader* header = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
const uint8_t* image_end;
|
const uint8_t* image_end;
|
||||||
const uint8_t* desc_start;
|
const uint8_t* desc_start;
|
||||||
const uint8_t* desc_end;
|
const uint8_t* desc_end;
|
||||||
const uint8_t* p;
|
const uint8_t* p;
|
||||||
|
|
||||||
if (image_data == NULL) {
|
if (image_data == NULL) {
|
||||||
avb_error("image_data is NULL\n.");
|
avb_error("image_data is NULL\n.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foreach_func == NULL) {
|
if (foreach_func == NULL) {
|
||||||
avb_error("foreach_func is NULL\n.");
|
avb_error("foreach_func is NULL\n.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image_size < sizeof(AvbVBMetaImageHeader)) {
|
if (image_size < sizeof(AvbVBMetaImageHeader)) {
|
||||||
avb_error("Length is smaller than header.\n");
|
avb_error("Length is smaller than header.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure magic is correct. */
|
/* Ensure magic is correct. */
|
||||||
if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
|
if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
|
||||||
avb_error("Magic is incorrect.\n");
|
avb_error("Magic is incorrect.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Careful, not byteswapped - also ensure it's aligned properly. */
|
/* Careful, not byteswapped - also ensure it's aligned properly. */
|
||||||
avb_assert_aligned(image_data);
|
avb_assert_aligned(image_data);
|
||||||
header = (const AvbVBMetaImageHeader*)image_data;
|
header = (const AvbVBMetaImageHeader*)image_data;
|
||||||
image_end = image_data + image_size;
|
image_end = image_data + image_size;
|
||||||
|
|
||||||
desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
|
desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
|
||||||
avb_be64toh(header->authentication_data_block_size) +
|
avb_be64toh(header->authentication_data_block_size) +
|
||||||
avb_be64toh(header->descriptors_offset);
|
avb_be64toh(header->descriptors_offset);
|
||||||
|
|
||||||
desc_end = desc_start + avb_be64toh(header->descriptors_size);
|
desc_end = desc_start + avb_be64toh(header->descriptors_size);
|
||||||
|
|
||||||
if (desc_start < image_data || desc_start > image_end ||
|
if (desc_start < image_data || desc_start > image_end ||
|
||||||
desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
|
desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
|
||||||
avb_error("Descriptors not inside passed-in data.\n");
|
avb_error("Descriptors not inside passed-in data.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = desc_start; p < desc_end;) {
|
for (p = desc_start; p < desc_end;) {
|
||||||
const AvbDescriptor* dh = (const AvbDescriptor*)p;
|
const AvbDescriptor* dh = (const AvbDescriptor*)p;
|
||||||
avb_assert_aligned(dh);
|
avb_assert_aligned(dh);
|
||||||
uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
|
uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
|
||||||
uint64_t nb_total = sizeof(AvbDescriptor) + nb_following;
|
uint64_t nb_total = 0;
|
||||||
|
if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) {
|
||||||
if ((nb_total & 7) != 0) {
|
avb_error("Invalid descriptor length.\n");
|
||||||
avb_error("Invalid descriptor length.\n");
|
goto out;
|
||||||
goto out;
|
}
|
||||||
}
|
|
||||||
|
if ((nb_total & 7) != 0) {
|
||||||
if (nb_total + p < desc_start || nb_total + p > desc_end) {
|
avb_error("Invalid descriptor length.\n");
|
||||||
avb_error("Invalid data in descriptors array.\n");
|
goto out;
|
||||||
goto out;
|
}
|
||||||
}
|
|
||||||
|
if (nb_total + p < desc_start || nb_total + p > desc_end) {
|
||||||
if (foreach_func(dh, user_data) == 0) {
|
avb_error("Invalid data in descriptors array.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += nb_total;
|
if (foreach_func(dh, user_data) == 0) {
|
||||||
}
|
goto out;
|
||||||
|
}
|
||||||
ret = true;
|
|
||||||
|
if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) {
|
||||||
out:
|
avb_error("Invalid descriptor length.\n");
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
static bool count_descriptors(const AvbDescriptor* descriptor,
|
|
||||||
void* user_data) {
|
ret = true;
|
||||||
size_t* num_descriptors = user_data;
|
|
||||||
*num_descriptors += 1;
|
out:
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
static bool count_descriptors(const AvbDescriptor* descriptor,
|
||||||
size_t descriptor_number;
|
void* user_data) {
|
||||||
const AvbDescriptor** descriptors;
|
size_t* num_descriptors = user_data;
|
||||||
} SetDescriptorData;
|
*num_descriptors += 1;
|
||||||
|
return true;
|
||||||
static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
|
}
|
||||||
SetDescriptorData* data = user_data;
|
|
||||||
data->descriptors[data->descriptor_number++] = descriptor;
|
typedef struct {
|
||||||
return true;
|
size_t descriptor_number;
|
||||||
}
|
const AvbDescriptor** descriptors;
|
||||||
|
} SetDescriptorData;
|
||||||
const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
|
|
||||||
size_t image_size,
|
static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
|
||||||
size_t* out_num_descriptors) {
|
SetDescriptorData* data = user_data;
|
||||||
size_t num_descriptors = 0;
|
data->descriptors[data->descriptor_number++] = descriptor;
|
||||||
SetDescriptorData data;
|
return true;
|
||||||
|
}
|
||||||
avb_descriptor_foreach(
|
|
||||||
image_data, image_size, count_descriptors, &num_descriptors);
|
const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
|
||||||
|
size_t image_size,
|
||||||
data.descriptor_number = 0;
|
size_t* out_num_descriptors) {
|
||||||
data.descriptors =
|
size_t num_descriptors = 0;
|
||||||
avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
|
SetDescriptorData data;
|
||||||
if (data.descriptors == NULL) {
|
|
||||||
return NULL;
|
avb_descriptor_foreach(
|
||||||
}
|
image_data, image_size, count_descriptors, &num_descriptors);
|
||||||
avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
|
|
||||||
avb_assert(data.descriptor_number == num_descriptors);
|
data.descriptor_number = 0;
|
||||||
|
data.descriptors =
|
||||||
if (out_num_descriptors != NULL) {
|
avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
|
||||||
*out_num_descriptors = num_descriptors;
|
if (data.descriptors == NULL) {
|
||||||
}
|
return NULL;
|
||||||
|
}
|
||||||
return data.descriptors;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,390 +1,402 @@
|
||||||
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||||
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||||
* Last update: 02/02/2007
|
* Last update: 02/02/2007
|
||||||
* Issue date: 04/30/2005
|
* Issue date: 04/30/2005
|
||||||
*
|
*
|
||||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the name of the project nor the names of its contributors
|
* 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
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* 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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <android_avb/avb_sha.h>
|
#include <android_avb/avb_sha.h>
|
||||||
|
|
||||||
#define SHFR(x, n) (x >> n)
|
#define SHFR(x, n) (x >> n)
|
||||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||||
#define ROTL(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 CH(x, y, z) ((x & y) ^ (~x & z))
|
||||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & 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_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_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_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 SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||||
|
|
||||||
#define UNPACK32(x, str) \
|
#define UNPACK32(x, str) \
|
||||||
{ \
|
{ \
|
||||||
*((str) + 3) = (uint8_t)((x)); \
|
*((str) + 3) = (uint8_t)((x)); \
|
||||||
*((str) + 2) = (uint8_t)((x) >> 8); \
|
*((str) + 2) = (uint8_t)((x) >> 8); \
|
||||||
*((str) + 1) = (uint8_t)((x) >> 16); \
|
*((str) + 1) = (uint8_t)((x) >> 16); \
|
||||||
*((str) + 0) = (uint8_t)((x) >> 24); \
|
*((str) + 0) = (uint8_t)((x) >> 24); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PACK32(str, x) \
|
#define UNPACK64(x, str) \
|
||||||
{ \
|
{ \
|
||||||
*(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
|
*((str) + 7) = (uint8_t)x; \
|
||||||
((uint32_t) * ((str) + 1) << 16) | \
|
*((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
|
||||||
((uint32_t) * ((str) + 0) << 24); \
|
*((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
|
||||||
}
|
*((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
|
||||||
|
*((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
|
||||||
/* Macros used for loops unrolling */
|
*((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
|
||||||
|
*((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
|
||||||
#define SHA256_SCR(i) \
|
*((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
|
||||||
{ 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) \
|
#define PACK32(str, x) \
|
||||||
{ \
|
{ \
|
||||||
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
|
*(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
|
||||||
w[j]; \
|
((uint32_t) * ((str) + 1) << 16) | \
|
||||||
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
((uint32_t) * ((str) + 0) << 24); \
|
||||||
wv[d] += t1; \
|
}
|
||||||
wv[h] = t1 + t2; \
|
|
||||||
}
|
/* Macros used for loops unrolling */
|
||||||
|
|
||||||
static const uint32_t sha256_h0[8] = {0x6a09e667,
|
#define SHA256_SCR(i) \
|
||||||
0xbb67ae85,
|
{ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; }
|
||||||
0x3c6ef372,
|
|
||||||
0xa54ff53a,
|
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
||||||
0x510e527f,
|
{ \
|
||||||
0x9b05688c,
|
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
|
||||||
0x1f83d9ab,
|
w[j]; \
|
||||||
0x5be0cd19};
|
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||||
|
wv[d] += t1; \
|
||||||
static const uint32_t sha256_k[64] = {
|
wv[h] = t1 + t2; \
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
}
|
||||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
||||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
static const uint32_t sha256_h0[8] = {0x6a09e667,
|
||||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
0xbb67ae85,
|
||||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
0x3c6ef372,
|
||||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
0xa54ff53a,
|
||||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
0x510e527f,
|
||||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
0x9b05688c,
|
||||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
0x1f83d9ab,
|
||||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
0x5be0cd19};
|
||||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
|
||||||
|
static const uint32_t sha256_k[64] = {
|
||||||
/* SHA-256 implementation */
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||||
void avb_sha256_init(AvbSHA256Ctx* ctx) {
|
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
#ifndef UNROLL_LOOPS
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||||
int i;
|
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
for (i = 0; i < 8; i++) {
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||||
ctx->h[i] = sha256_h0[i];
|
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
}
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||||
#else
|
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
ctx->h[0] = sha256_h0[0];
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||||
ctx->h[1] = sha256_h0[1];
|
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||||
ctx->h[2] = sha256_h0[2];
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||||
ctx->h[3] = sha256_h0[3];
|
|
||||||
ctx->h[4] = sha256_h0[4];
|
/* SHA-256 implementation */
|
||||||
ctx->h[5] = sha256_h0[5];
|
void avb_sha256_init(AvbSHA256Ctx* ctx) {
|
||||||
ctx->h[6] = sha256_h0[6];
|
#ifndef UNROLL_LOOPS
|
||||||
ctx->h[7] = sha256_h0[7];
|
int i;
|
||||||
#endif /* !UNROLL_LOOPS */
|
for (i = 0; i < 8; i++) {
|
||||||
|
ctx->h[i] = sha256_h0[i];
|
||||||
ctx->len = 0;
|
}
|
||||||
ctx->tot_len = 0;
|
#else
|
||||||
}
|
ctx->h[0] = sha256_h0[0];
|
||||||
|
ctx->h[1] = sha256_h0[1];
|
||||||
static void SHA256_transform(AvbSHA256Ctx* ctx,
|
ctx->h[2] = sha256_h0[2];
|
||||||
const uint8_t* message,
|
ctx->h[3] = sha256_h0[3];
|
||||||
unsigned int block_nb) {
|
ctx->h[4] = sha256_h0[4];
|
||||||
uint32_t w[64];
|
ctx->h[5] = sha256_h0[5];
|
||||||
uint32_t wv[8];
|
ctx->h[6] = sha256_h0[6];
|
||||||
uint32_t t1, t2;
|
ctx->h[7] = sha256_h0[7];
|
||||||
const unsigned char* sub_block;
|
#endif /* !UNROLL_LOOPS */
|
||||||
int i;
|
|
||||||
|
ctx->len = 0;
|
||||||
#ifndef UNROLL_LOOPS
|
ctx->tot_len = 0;
|
||||||
int j;
|
}
|
||||||
#endif
|
|
||||||
|
static void SHA256_transform(AvbSHA256Ctx* ctx,
|
||||||
for (i = 0; i < (int)block_nb; i++) {
|
const uint8_t* message,
|
||||||
sub_block = message + (i << 6);
|
size_t block_nb) {
|
||||||
|
uint32_t w[64];
|
||||||
#ifndef UNROLL_LOOPS
|
uint32_t wv[8];
|
||||||
for (j = 0; j < 16; j++) {
|
uint32_t t1, t2;
|
||||||
PACK32(&sub_block[j << 2], &w[j]);
|
const unsigned char* sub_block;
|
||||||
}
|
size_t i;
|
||||||
|
|
||||||
for (j = 16; j < 64; j++) {
|
#ifndef UNROLL_LOOPS
|
||||||
SHA256_SCR(j);
|
size_t j;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
for (j = 0; j < 8; j++) {
|
for (i = 0; i < block_nb; i++) {
|
||||||
wv[j] = ctx->h[j];
|
sub_block = message + (i << 6);
|
||||||
}
|
|
||||||
|
#ifndef UNROLL_LOOPS
|
||||||
for (j = 0; j < 64; j++) {
|
for (j = 0; j < 16; j++) {
|
||||||
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
|
PACK32(&sub_block[j << 2], &w[j]);
|
||||||
w[j];
|
}
|
||||||
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
|
||||||
wv[7] = wv[6];
|
for (j = 16; j < 64; j++) {
|
||||||
wv[6] = wv[5];
|
SHA256_SCR(j);
|
||||||
wv[5] = wv[4];
|
}
|
||||||
wv[4] = wv[3] + t1;
|
|
||||||
wv[3] = wv[2];
|
for (j = 0; j < 8; j++) {
|
||||||
wv[2] = wv[1];
|
wv[j] = ctx->h[j];
|
||||||
wv[1] = wv[0];
|
}
|
||||||
wv[0] = t1 + t2;
|
|
||||||
}
|
for (j = 0; j < 64; j++) {
|
||||||
|
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
|
||||||
for (j = 0; j < 8; j++) {
|
w[j];
|
||||||
ctx->h[j] += wv[j];
|
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||||
}
|
wv[7] = wv[6];
|
||||||
#else
|
wv[6] = wv[5];
|
||||||
PACK32(&sub_block[0], &w[0]);
|
wv[5] = wv[4];
|
||||||
PACK32(&sub_block[4], &w[1]);
|
wv[4] = wv[3] + t1;
|
||||||
PACK32(&sub_block[8], &w[2]);
|
wv[3] = wv[2];
|
||||||
PACK32(&sub_block[12], &w[3]);
|
wv[2] = wv[1];
|
||||||
PACK32(&sub_block[16], &w[4]);
|
wv[1] = wv[0];
|
||||||
PACK32(&sub_block[20], &w[5]);
|
wv[0] = t1 + t2;
|
||||||
PACK32(&sub_block[24], &w[6]);
|
}
|
||||||
PACK32(&sub_block[28], &w[7]);
|
|
||||||
PACK32(&sub_block[32], &w[8]);
|
for (j = 0; j < 8; j++) {
|
||||||
PACK32(&sub_block[36], &w[9]);
|
ctx->h[j] += wv[j];
|
||||||
PACK32(&sub_block[40], &w[10]);
|
}
|
||||||
PACK32(&sub_block[44], &w[11]);
|
#else
|
||||||
PACK32(&sub_block[48], &w[12]);
|
PACK32(&sub_block[0], &w[0]);
|
||||||
PACK32(&sub_block[52], &w[13]);
|
PACK32(&sub_block[4], &w[1]);
|
||||||
PACK32(&sub_block[56], &w[14]);
|
PACK32(&sub_block[8], &w[2]);
|
||||||
PACK32(&sub_block[60], &w[15]);
|
PACK32(&sub_block[12], &w[3]);
|
||||||
|
PACK32(&sub_block[16], &w[4]);
|
||||||
SHA256_SCR(16);
|
PACK32(&sub_block[20], &w[5]);
|
||||||
SHA256_SCR(17);
|
PACK32(&sub_block[24], &w[6]);
|
||||||
SHA256_SCR(18);
|
PACK32(&sub_block[28], &w[7]);
|
||||||
SHA256_SCR(19);
|
PACK32(&sub_block[32], &w[8]);
|
||||||
SHA256_SCR(20);
|
PACK32(&sub_block[36], &w[9]);
|
||||||
SHA256_SCR(21);
|
PACK32(&sub_block[40], &w[10]);
|
||||||
SHA256_SCR(22);
|
PACK32(&sub_block[44], &w[11]);
|
||||||
SHA256_SCR(23);
|
PACK32(&sub_block[48], &w[12]);
|
||||||
SHA256_SCR(24);
|
PACK32(&sub_block[52], &w[13]);
|
||||||
SHA256_SCR(25);
|
PACK32(&sub_block[56], &w[14]);
|
||||||
SHA256_SCR(26);
|
PACK32(&sub_block[60], &w[15]);
|
||||||
SHA256_SCR(27);
|
|
||||||
SHA256_SCR(28);
|
SHA256_SCR(16);
|
||||||
SHA256_SCR(29);
|
SHA256_SCR(17);
|
||||||
SHA256_SCR(30);
|
SHA256_SCR(18);
|
||||||
SHA256_SCR(31);
|
SHA256_SCR(19);
|
||||||
SHA256_SCR(32);
|
SHA256_SCR(20);
|
||||||
SHA256_SCR(33);
|
SHA256_SCR(21);
|
||||||
SHA256_SCR(34);
|
SHA256_SCR(22);
|
||||||
SHA256_SCR(35);
|
SHA256_SCR(23);
|
||||||
SHA256_SCR(36);
|
SHA256_SCR(24);
|
||||||
SHA256_SCR(37);
|
SHA256_SCR(25);
|
||||||
SHA256_SCR(38);
|
SHA256_SCR(26);
|
||||||
SHA256_SCR(39);
|
SHA256_SCR(27);
|
||||||
SHA256_SCR(40);
|
SHA256_SCR(28);
|
||||||
SHA256_SCR(41);
|
SHA256_SCR(29);
|
||||||
SHA256_SCR(42);
|
SHA256_SCR(30);
|
||||||
SHA256_SCR(43);
|
SHA256_SCR(31);
|
||||||
SHA256_SCR(44);
|
SHA256_SCR(32);
|
||||||
SHA256_SCR(45);
|
SHA256_SCR(33);
|
||||||
SHA256_SCR(46);
|
SHA256_SCR(34);
|
||||||
SHA256_SCR(47);
|
SHA256_SCR(35);
|
||||||
SHA256_SCR(48);
|
SHA256_SCR(36);
|
||||||
SHA256_SCR(49);
|
SHA256_SCR(37);
|
||||||
SHA256_SCR(50);
|
SHA256_SCR(38);
|
||||||
SHA256_SCR(51);
|
SHA256_SCR(39);
|
||||||
SHA256_SCR(52);
|
SHA256_SCR(40);
|
||||||
SHA256_SCR(53);
|
SHA256_SCR(41);
|
||||||
SHA256_SCR(54);
|
SHA256_SCR(42);
|
||||||
SHA256_SCR(55);
|
SHA256_SCR(43);
|
||||||
SHA256_SCR(56);
|
SHA256_SCR(44);
|
||||||
SHA256_SCR(57);
|
SHA256_SCR(45);
|
||||||
SHA256_SCR(58);
|
SHA256_SCR(46);
|
||||||
SHA256_SCR(59);
|
SHA256_SCR(47);
|
||||||
SHA256_SCR(60);
|
SHA256_SCR(48);
|
||||||
SHA256_SCR(61);
|
SHA256_SCR(49);
|
||||||
SHA256_SCR(62);
|
SHA256_SCR(50);
|
||||||
SHA256_SCR(63);
|
SHA256_SCR(51);
|
||||||
|
SHA256_SCR(52);
|
||||||
wv[0] = ctx->h[0];
|
SHA256_SCR(53);
|
||||||
wv[1] = ctx->h[1];
|
SHA256_SCR(54);
|
||||||
wv[2] = ctx->h[2];
|
SHA256_SCR(55);
|
||||||
wv[3] = ctx->h[3];
|
SHA256_SCR(56);
|
||||||
wv[4] = ctx->h[4];
|
SHA256_SCR(57);
|
||||||
wv[5] = ctx->h[5];
|
SHA256_SCR(58);
|
||||||
wv[6] = ctx->h[6];
|
SHA256_SCR(59);
|
||||||
wv[7] = ctx->h[7];
|
SHA256_SCR(60);
|
||||||
|
SHA256_SCR(61);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
|
SHA256_SCR(62);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
|
SHA256_SCR(63);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
|
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
|
wv[0] = ctx->h[0];
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
|
wv[1] = ctx->h[1];
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
|
wv[2] = ctx->h[2];
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
|
wv[3] = ctx->h[3];
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
|
wv[4] = ctx->h[4];
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
|
wv[5] = ctx->h[5];
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
|
wv[6] = ctx->h[6];
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
|
wv[7] = ctx->h[7];
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
|
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
|
||||||
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
|
||||||
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
|
||||||
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
|
||||||
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
|
||||||
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
|
||||||
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
|
||||||
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
|
||||||
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
|
||||||
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
|
||||||
ctx->h[0] += wv[0];
|
SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
|
||||||
ctx->h[1] += wv[1];
|
SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
|
||||||
ctx->h[2] += wv[2];
|
SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
|
||||||
ctx->h[3] += wv[3];
|
SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
|
||||||
ctx->h[4] += wv[4];
|
SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
|
||||||
ctx->h[5] += wv[5];
|
SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
|
||||||
ctx->h[6] += wv[6];
|
SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
|
||||||
ctx->h[7] += wv[7];
|
SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
|
||||||
#endif /* !UNROLL_LOOPS */
|
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);
|
||||||
|
|
||||||
void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len) {
|
ctx->h[0] += wv[0];
|
||||||
unsigned int block_nb;
|
ctx->h[1] += wv[1];
|
||||||
unsigned int new_len, rem_len, tmp_len;
|
ctx->h[2] += wv[2];
|
||||||
const uint8_t* shifted_data;
|
ctx->h[3] += wv[3];
|
||||||
|
ctx->h[4] += wv[4];
|
||||||
tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
|
ctx->h[5] += wv[5];
|
||||||
rem_len = len < tmp_len ? len : tmp_len;
|
ctx->h[6] += wv[6];
|
||||||
|
ctx->h[7] += wv[7];
|
||||||
avb_memcpy(&ctx->block[ctx->len], data, rem_len);
|
#endif /* !UNROLL_LOOPS */
|
||||||
|
}
|
||||||
if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
|
}
|
||||||
ctx->len += len;
|
|
||||||
return;
|
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;
|
||||||
new_len = len - rem_len;
|
const uint8_t* shifted_data;
|
||||||
block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
|
|
||||||
|
tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
|
||||||
shifted_data = data + rem_len;
|
rem_len = len < tmp_len ? len : tmp_len;
|
||||||
|
|
||||||
SHA256_transform(ctx, ctx->block, 1);
|
avb_memcpy(&ctx->block[ctx->len], data, rem_len);
|
||||||
SHA256_transform(ctx, shifted_data, block_nb);
|
|
||||||
|
if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
|
||||||
rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
|
ctx->len += len;
|
||||||
|
return;
|
||||||
avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
|
}
|
||||||
|
|
||||||
ctx->len = rem_len;
|
new_len = len - rem_len;
|
||||||
ctx->tot_len += (block_nb + 1) << 6;
|
block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
|
||||||
}
|
|
||||||
|
shifted_data = data + rem_len;
|
||||||
uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
|
|
||||||
unsigned int block_nb;
|
SHA256_transform(ctx, ctx->block, 1);
|
||||||
unsigned int pm_len;
|
SHA256_transform(ctx, shifted_data, block_nb);
|
||||||
unsigned int len_b;
|
|
||||||
#ifndef UNROLL_LOOPS
|
rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
|
||||||
int i;
|
|
||||||
#endif
|
avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
|
||||||
|
|
||||||
block_nb =
|
ctx->len = rem_len;
|
||||||
(1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
|
ctx->tot_len += (block_nb + 1) << 6;
|
||||||
|
}
|
||||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
|
||||||
pm_len = block_nb << 6;
|
uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
|
||||||
|
size_t block_nb;
|
||||||
avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
size_t pm_len;
|
||||||
ctx->block[ctx->len] = 0x80;
|
uint64_t len_b;
|
||||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
#ifndef UNROLL_LOOPS
|
||||||
|
size_t i;
|
||||||
SHA256_transform(ctx, ctx->block, block_nb);
|
#endif
|
||||||
|
|
||||||
#ifndef UNROLL_LOOPS
|
block_nb =
|
||||||
for (i = 0; i < 8; i++) {
|
(1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
|
||||||
UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
|
|
||||||
}
|
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||||
#else
|
pm_len = block_nb << 6;
|
||||||
UNPACK32(ctx->h[0], &ctx->buf[0]);
|
|
||||||
UNPACK32(ctx->h[1], &ctx->buf[4]);
|
avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||||
UNPACK32(ctx->h[2], &ctx->buf[8]);
|
ctx->block[ctx->len] = 0x80;
|
||||||
UNPACK32(ctx->h[3], &ctx->buf[12]);
|
UNPACK64(len_b, ctx->block + pm_len - 8);
|
||||||
UNPACK32(ctx->h[4], &ctx->buf[16]);
|
|
||||||
UNPACK32(ctx->h[5], &ctx->buf[20]);
|
SHA256_transform(ctx, ctx->block, block_nb);
|
||||||
UNPACK32(ctx->h[6], &ctx->buf[24]);
|
|
||||||
UNPACK32(ctx->h[7], &ctx->buf[28]);
|
#ifndef UNROLL_LOOPS
|
||||||
#endif /* !UNROLL_LOOPS */
|
for (i = 0; i < 8; i++) {
|
||||||
|
UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
|
||||||
return ctx->buf;
|
}
|
||||||
}
|
#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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,388 +1,388 @@
|
||||||
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||||
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||||
* Last update: 02/02/2007
|
* Last update: 02/02/2007
|
||||||
* Issue date: 04/30/2005
|
* Issue date: 04/30/2005
|
||||||
*
|
*
|
||||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the name of the project nor the names of its contributors
|
* 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
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* 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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <android_avb/avb_sha.h>
|
#include <android_avb/avb_sha.h>
|
||||||
|
|
||||||
#define SHFR(x, n) (x >> n)
|
#define SHFR(x, n) (x >> n)
|
||||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||||
#define ROTL(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 CH(x, y, z) ((x & y) ^ (~x & z))
|
||||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & 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_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_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_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 SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
||||||
|
|
||||||
#define UNPACK32(x, str) \
|
#define UNPACK32(x, str) \
|
||||||
{ \
|
{ \
|
||||||
*((str) + 3) = (uint8_t)((x)); \
|
*((str) + 3) = (uint8_t)((x)); \
|
||||||
*((str) + 2) = (uint8_t)((x) >> 8); \
|
*((str) + 2) = (uint8_t)((x) >> 8); \
|
||||||
*((str) + 1) = (uint8_t)((x) >> 16); \
|
*((str) + 1) = (uint8_t)((x) >> 16); \
|
||||||
*((str) + 0) = (uint8_t)((x) >> 24); \
|
*((str) + 0) = (uint8_t)((x) >> 24); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define UNPACK64(x, str) \
|
#define UNPACK64(x, str) \
|
||||||
{ \
|
{ \
|
||||||
*((str) + 7) = (uint8_t)x; \
|
*((str) + 7) = (uint8_t)x; \
|
||||||
*((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
|
*((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
|
||||||
*((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
|
*((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
|
||||||
*((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
|
*((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
|
||||||
*((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
|
*((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
|
||||||
*((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
|
*((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
|
||||||
*((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
|
*((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
|
||||||
*((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
|
*((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PACK64(str, x) \
|
#define PACK64(str, x) \
|
||||||
{ \
|
{ \
|
||||||
*(x) = \
|
*(x) = \
|
||||||
((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) | \
|
((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) | \
|
||||||
((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
|
((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
|
||||||
((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
|
((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
|
||||||
((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56); \
|
((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Macros used for loops unrolling */
|
/* Macros used for loops unrolling */
|
||||||
|
|
||||||
#define SHA512_SCR(i) \
|
#define SHA512_SCR(i) \
|
||||||
{ w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; }
|
{ 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) \
|
#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] + \
|
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + \
|
||||||
w[j]; \
|
w[j]; \
|
||||||
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||||
wv[d] += t1; \
|
wv[d] += t1; \
|
||||||
wv[h] = t1 + t2; \
|
wv[h] = t1 + t2; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
|
static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
|
||||||
0xbb67ae8584caa73bULL,
|
0xbb67ae8584caa73bULL,
|
||||||
0x3c6ef372fe94f82bULL,
|
0x3c6ef372fe94f82bULL,
|
||||||
0xa54ff53a5f1d36f1ULL,
|
0xa54ff53a5f1d36f1ULL,
|
||||||
0x510e527fade682d1ULL,
|
0x510e527fade682d1ULL,
|
||||||
0x9b05688c2b3e6c1fULL,
|
0x9b05688c2b3e6c1fULL,
|
||||||
0x1f83d9abfb41bd6bULL,
|
0x1f83d9abfb41bd6bULL,
|
||||||
0x5be0cd19137e2179ULL};
|
0x5be0cd19137e2179ULL};
|
||||||
|
|
||||||
static const uint64_t sha512_k[80] = {
|
static const uint64_t sha512_k[80] = {
|
||||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
|
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
|
||||||
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
|
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
|
||||||
0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
|
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
|
||||||
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
|
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
|
||||||
0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
|
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
|
||||||
0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
|
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
|
||||||
0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
|
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
|
||||||
0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
|
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
|
||||||
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
|
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
|
||||||
0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
|
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
|
||||||
0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
|
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
|
||||||
0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
|
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
|
||||||
0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
|
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
|
||||||
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
||||||
|
|
||||||
/* SHA-512 implementation */
|
/* SHA-512 implementation */
|
||||||
|
|
||||||
void avb_sha512_init(AvbSHA512Ctx* ctx) {
|
void avb_sha512_init(AvbSHA512Ctx* ctx) {
|
||||||
#ifdef UNROLL_LOOPS_SHA512
|
#ifdef UNROLL_LOOPS_SHA512
|
||||||
ctx->h[0] = sha512_h0[0];
|
ctx->h[0] = sha512_h0[0];
|
||||||
ctx->h[1] = sha512_h0[1];
|
ctx->h[1] = sha512_h0[1];
|
||||||
ctx->h[2] = sha512_h0[2];
|
ctx->h[2] = sha512_h0[2];
|
||||||
ctx->h[3] = sha512_h0[3];
|
ctx->h[3] = sha512_h0[3];
|
||||||
ctx->h[4] = sha512_h0[4];
|
ctx->h[4] = sha512_h0[4];
|
||||||
ctx->h[5] = sha512_h0[5];
|
ctx->h[5] = sha512_h0[5];
|
||||||
ctx->h[6] = sha512_h0[6];
|
ctx->h[6] = sha512_h0[6];
|
||||||
ctx->h[7] = sha512_h0[7];
|
ctx->h[7] = sha512_h0[7];
|
||||||
#else
|
#else
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
ctx->h[i] = sha512_h0[i];
|
ctx->h[i] = sha512_h0[i];
|
||||||
#endif /* UNROLL_LOOPS_SHA512 */
|
#endif /* UNROLL_LOOPS_SHA512 */
|
||||||
|
|
||||||
ctx->len = 0;
|
ctx->len = 0;
|
||||||
ctx->tot_len = 0;
|
ctx->tot_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SHA512_transform(AvbSHA512Ctx* ctx,
|
static void SHA512_transform(AvbSHA512Ctx* ctx,
|
||||||
const uint8_t* message,
|
const uint8_t* message,
|
||||||
unsigned int block_nb) {
|
size_t block_nb) {
|
||||||
uint64_t w[80];
|
uint64_t w[80];
|
||||||
uint64_t wv[8];
|
uint64_t wv[8];
|
||||||
uint64_t t1, t2;
|
uint64_t t1, t2;
|
||||||
const uint8_t* sub_block;
|
const uint8_t* sub_block;
|
||||||
int i, j;
|
size_t i, j;
|
||||||
|
|
||||||
for (i = 0; i < (int)block_nb; i++) {
|
for (i = 0; i < block_nb; i++) {
|
||||||
sub_block = message + (i << 7);
|
sub_block = message + (i << 7);
|
||||||
|
|
||||||
#ifdef UNROLL_LOOPS_SHA512
|
#ifdef UNROLL_LOOPS_SHA512
|
||||||
PACK64(&sub_block[0], &w[0]);
|
PACK64(&sub_block[0], &w[0]);
|
||||||
PACK64(&sub_block[8], &w[1]);
|
PACK64(&sub_block[8], &w[1]);
|
||||||
PACK64(&sub_block[16], &w[2]);
|
PACK64(&sub_block[16], &w[2]);
|
||||||
PACK64(&sub_block[24], &w[3]);
|
PACK64(&sub_block[24], &w[3]);
|
||||||
PACK64(&sub_block[32], &w[4]);
|
PACK64(&sub_block[32], &w[4]);
|
||||||
PACK64(&sub_block[40], &w[5]);
|
PACK64(&sub_block[40], &w[5]);
|
||||||
PACK64(&sub_block[48], &w[6]);
|
PACK64(&sub_block[48], &w[6]);
|
||||||
PACK64(&sub_block[56], &w[7]);
|
PACK64(&sub_block[56], &w[7]);
|
||||||
PACK64(&sub_block[64], &w[8]);
|
PACK64(&sub_block[64], &w[8]);
|
||||||
PACK64(&sub_block[72], &w[9]);
|
PACK64(&sub_block[72], &w[9]);
|
||||||
PACK64(&sub_block[80], &w[10]);
|
PACK64(&sub_block[80], &w[10]);
|
||||||
PACK64(&sub_block[88], &w[11]);
|
PACK64(&sub_block[88], &w[11]);
|
||||||
PACK64(&sub_block[96], &w[12]);
|
PACK64(&sub_block[96], &w[12]);
|
||||||
PACK64(&sub_block[104], &w[13]);
|
PACK64(&sub_block[104], &w[13]);
|
||||||
PACK64(&sub_block[112], &w[14]);
|
PACK64(&sub_block[112], &w[14]);
|
||||||
PACK64(&sub_block[120], &w[15]);
|
PACK64(&sub_block[120], &w[15]);
|
||||||
|
|
||||||
SHA512_SCR(16);
|
SHA512_SCR(16);
|
||||||
SHA512_SCR(17);
|
SHA512_SCR(17);
|
||||||
SHA512_SCR(18);
|
SHA512_SCR(18);
|
||||||
SHA512_SCR(19);
|
SHA512_SCR(19);
|
||||||
SHA512_SCR(20);
|
SHA512_SCR(20);
|
||||||
SHA512_SCR(21);
|
SHA512_SCR(21);
|
||||||
SHA512_SCR(22);
|
SHA512_SCR(22);
|
||||||
SHA512_SCR(23);
|
SHA512_SCR(23);
|
||||||
SHA512_SCR(24);
|
SHA512_SCR(24);
|
||||||
SHA512_SCR(25);
|
SHA512_SCR(25);
|
||||||
SHA512_SCR(26);
|
SHA512_SCR(26);
|
||||||
SHA512_SCR(27);
|
SHA512_SCR(27);
|
||||||
SHA512_SCR(28);
|
SHA512_SCR(28);
|
||||||
SHA512_SCR(29);
|
SHA512_SCR(29);
|
||||||
SHA512_SCR(30);
|
SHA512_SCR(30);
|
||||||
SHA512_SCR(31);
|
SHA512_SCR(31);
|
||||||
SHA512_SCR(32);
|
SHA512_SCR(32);
|
||||||
SHA512_SCR(33);
|
SHA512_SCR(33);
|
||||||
SHA512_SCR(34);
|
SHA512_SCR(34);
|
||||||
SHA512_SCR(35);
|
SHA512_SCR(35);
|
||||||
SHA512_SCR(36);
|
SHA512_SCR(36);
|
||||||
SHA512_SCR(37);
|
SHA512_SCR(37);
|
||||||
SHA512_SCR(38);
|
SHA512_SCR(38);
|
||||||
SHA512_SCR(39);
|
SHA512_SCR(39);
|
||||||
SHA512_SCR(40);
|
SHA512_SCR(40);
|
||||||
SHA512_SCR(41);
|
SHA512_SCR(41);
|
||||||
SHA512_SCR(42);
|
SHA512_SCR(42);
|
||||||
SHA512_SCR(43);
|
SHA512_SCR(43);
|
||||||
SHA512_SCR(44);
|
SHA512_SCR(44);
|
||||||
SHA512_SCR(45);
|
SHA512_SCR(45);
|
||||||
SHA512_SCR(46);
|
SHA512_SCR(46);
|
||||||
SHA512_SCR(47);
|
SHA512_SCR(47);
|
||||||
SHA512_SCR(48);
|
SHA512_SCR(48);
|
||||||
SHA512_SCR(49);
|
SHA512_SCR(49);
|
||||||
SHA512_SCR(50);
|
SHA512_SCR(50);
|
||||||
SHA512_SCR(51);
|
SHA512_SCR(51);
|
||||||
SHA512_SCR(52);
|
SHA512_SCR(52);
|
||||||
SHA512_SCR(53);
|
SHA512_SCR(53);
|
||||||
SHA512_SCR(54);
|
SHA512_SCR(54);
|
||||||
SHA512_SCR(55);
|
SHA512_SCR(55);
|
||||||
SHA512_SCR(56);
|
SHA512_SCR(56);
|
||||||
SHA512_SCR(57);
|
SHA512_SCR(57);
|
||||||
SHA512_SCR(58);
|
SHA512_SCR(58);
|
||||||
SHA512_SCR(59);
|
SHA512_SCR(59);
|
||||||
SHA512_SCR(60);
|
SHA512_SCR(60);
|
||||||
SHA512_SCR(61);
|
SHA512_SCR(61);
|
||||||
SHA512_SCR(62);
|
SHA512_SCR(62);
|
||||||
SHA512_SCR(63);
|
SHA512_SCR(63);
|
||||||
SHA512_SCR(64);
|
SHA512_SCR(64);
|
||||||
SHA512_SCR(65);
|
SHA512_SCR(65);
|
||||||
SHA512_SCR(66);
|
SHA512_SCR(66);
|
||||||
SHA512_SCR(67);
|
SHA512_SCR(67);
|
||||||
SHA512_SCR(68);
|
SHA512_SCR(68);
|
||||||
SHA512_SCR(69);
|
SHA512_SCR(69);
|
||||||
SHA512_SCR(70);
|
SHA512_SCR(70);
|
||||||
SHA512_SCR(71);
|
SHA512_SCR(71);
|
||||||
SHA512_SCR(72);
|
SHA512_SCR(72);
|
||||||
SHA512_SCR(73);
|
SHA512_SCR(73);
|
||||||
SHA512_SCR(74);
|
SHA512_SCR(74);
|
||||||
SHA512_SCR(75);
|
SHA512_SCR(75);
|
||||||
SHA512_SCR(76);
|
SHA512_SCR(76);
|
||||||
SHA512_SCR(77);
|
SHA512_SCR(77);
|
||||||
SHA512_SCR(78);
|
SHA512_SCR(78);
|
||||||
SHA512_SCR(79);
|
SHA512_SCR(79);
|
||||||
|
|
||||||
wv[0] = ctx->h[0];
|
wv[0] = ctx->h[0];
|
||||||
wv[1] = ctx->h[1];
|
wv[1] = ctx->h[1];
|
||||||
wv[2] = ctx->h[2];
|
wv[2] = ctx->h[2];
|
||||||
wv[3] = ctx->h[3];
|
wv[3] = ctx->h[3];
|
||||||
wv[4] = ctx->h[4];
|
wv[4] = ctx->h[4];
|
||||||
wv[5] = ctx->h[5];
|
wv[5] = ctx->h[5];
|
||||||
wv[6] = ctx->h[6];
|
wv[6] = ctx->h[6];
|
||||||
wv[7] = ctx->h[7];
|
wv[7] = ctx->h[7];
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
|
SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
|
SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
|
SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
|
SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
|
SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
|
SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
|
SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
|
||||||
j++;
|
j++;
|
||||||
SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
|
SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
|
||||||
j++;
|
j++;
|
||||||
} while (j < 80);
|
} while (j < 80);
|
||||||
|
|
||||||
ctx->h[0] += wv[0];
|
ctx->h[0] += wv[0];
|
||||||
ctx->h[1] += wv[1];
|
ctx->h[1] += wv[1];
|
||||||
ctx->h[2] += wv[2];
|
ctx->h[2] += wv[2];
|
||||||
ctx->h[3] += wv[3];
|
ctx->h[3] += wv[3];
|
||||||
ctx->h[4] += wv[4];
|
ctx->h[4] += wv[4];
|
||||||
ctx->h[5] += wv[5];
|
ctx->h[5] += wv[5];
|
||||||
ctx->h[6] += wv[6];
|
ctx->h[6] += wv[6];
|
||||||
ctx->h[7] += wv[7];
|
ctx->h[7] += wv[7];
|
||||||
#else
|
#else
|
||||||
for (j = 0; j < 16; j++) {
|
for (j = 0; j < 16; j++) {
|
||||||
PACK64(&sub_block[j << 3], &w[j]);
|
PACK64(&sub_block[j << 3], &w[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 16; j < 80; j++) {
|
for (j = 16; j < 80; j++) {
|
||||||
SHA512_SCR(j);
|
SHA512_SCR(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
wv[j] = ctx->h[j];
|
wv[j] = ctx->h[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 80; j++) {
|
for (j = 0; j < 80; j++) {
|
||||||
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
|
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
|
||||||
w[j];
|
w[j];
|
||||||
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||||
wv[7] = wv[6];
|
wv[7] = wv[6];
|
||||||
wv[6] = wv[5];
|
wv[6] = wv[5];
|
||||||
wv[5] = wv[4];
|
wv[5] = wv[4];
|
||||||
wv[4] = wv[3] + t1;
|
wv[4] = wv[3] + t1;
|
||||||
wv[3] = wv[2];
|
wv[3] = wv[2];
|
||||||
wv[2] = wv[1];
|
wv[2] = wv[1];
|
||||||
wv[1] = wv[0];
|
wv[1] = wv[0];
|
||||||
wv[0] = t1 + t2;
|
wv[0] = t1 + t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
ctx->h[j] += wv[j];
|
ctx->h[j] += wv[j];
|
||||||
#endif /* UNROLL_LOOPS_SHA512 */
|
#endif /* UNROLL_LOOPS_SHA512 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len) {
|
void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len) {
|
||||||
unsigned int block_nb;
|
size_t block_nb;
|
||||||
unsigned int new_len, rem_len, tmp_len;
|
size_t new_len, rem_len, tmp_len;
|
||||||
const uint8_t* shifted_data;
|
const uint8_t* shifted_data;
|
||||||
|
|
||||||
tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
|
tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
|
||||||
rem_len = len < tmp_len ? len : tmp_len;
|
rem_len = len < tmp_len ? len : tmp_len;
|
||||||
|
|
||||||
avb_memcpy(&ctx->block[ctx->len], data, rem_len);
|
avb_memcpy(&ctx->block[ctx->len], data, rem_len);
|
||||||
|
|
||||||
if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
|
if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
|
||||||
ctx->len += len;
|
ctx->len += len;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_len = len - rem_len;
|
new_len = len - rem_len;
|
||||||
block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
|
block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
|
||||||
|
|
||||||
shifted_data = data + rem_len;
|
shifted_data = data + rem_len;
|
||||||
|
|
||||||
SHA512_transform(ctx, ctx->block, 1);
|
SHA512_transform(ctx, ctx->block, 1);
|
||||||
SHA512_transform(ctx, shifted_data, block_nb);
|
SHA512_transform(ctx, shifted_data, block_nb);
|
||||||
|
|
||||||
rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
|
rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
|
||||||
|
|
||||||
avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
|
avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
|
||||||
|
|
||||||
ctx->len = rem_len;
|
ctx->len = rem_len;
|
||||||
ctx->tot_len += (block_nb + 1) << 7;
|
ctx->tot_len += (block_nb + 1) << 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
|
uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
|
||||||
unsigned int block_nb;
|
size_t block_nb;
|
||||||
unsigned int pm_len;
|
size_t pm_len;
|
||||||
unsigned int len_b;
|
uint64_t len_b;
|
||||||
|
|
||||||
#ifndef UNROLL_LOOPS_SHA512
|
#ifndef UNROLL_LOOPS_SHA512
|
||||||
int i;
|
size_t i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
block_nb =
|
block_nb =
|
||||||
1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
|
1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
|
||||||
|
|
||||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||||
pm_len = block_nb << 7;
|
pm_len = block_nb << 7;
|
||||||
|
|
||||||
avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||||
ctx->block[ctx->len] = 0x80;
|
ctx->block[ctx->len] = 0x80;
|
||||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
UNPACK64(len_b, ctx->block + pm_len - 8);
|
||||||
|
|
||||||
SHA512_transform(ctx, ctx->block, block_nb);
|
SHA512_transform(ctx, ctx->block, block_nb);
|
||||||
|
|
||||||
#ifdef UNROLL_LOOPS_SHA512
|
#ifdef UNROLL_LOOPS_SHA512
|
||||||
UNPACK64(ctx->h[0], &ctx->buf[0]);
|
UNPACK64(ctx->h[0], &ctx->buf[0]);
|
||||||
UNPACK64(ctx->h[1], &ctx->buf[8]);
|
UNPACK64(ctx->h[1], &ctx->buf[8]);
|
||||||
UNPACK64(ctx->h[2], &ctx->buf[16]);
|
UNPACK64(ctx->h[2], &ctx->buf[16]);
|
||||||
UNPACK64(ctx->h[3], &ctx->buf[24]);
|
UNPACK64(ctx->h[3], &ctx->buf[24]);
|
||||||
UNPACK64(ctx->h[4], &ctx->buf[32]);
|
UNPACK64(ctx->h[4], &ctx->buf[32]);
|
||||||
UNPACK64(ctx->h[5], &ctx->buf[40]);
|
UNPACK64(ctx->h[5], &ctx->buf[40]);
|
||||||
UNPACK64(ctx->h[6], &ctx->buf[48]);
|
UNPACK64(ctx->h[6], &ctx->buf[48]);
|
||||||
UNPACK64(ctx->h[7], &ctx->buf[56]);
|
UNPACK64(ctx->h[7], &ctx->buf[56]);
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
|
UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
|
||||||
#endif /* UNROLL_LOOPS_SHA512 */
|
#endif /* UNROLL_LOOPS_SHA512 */
|
||||||
|
|
||||||
return ctx->buf;
|
return ctx->buf;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -52,6 +52,10 @@ int avb_strcmp(const char* s1, const char* s2) {
|
||||||
return strcmp(s1, 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) {
|
size_t avb_strlen(const char* str) {
|
||||||
return strlen(str);
|
return strlen(str);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,308 +1,309 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* obtaining a copy of this software and associated documentation
|
* obtaining a copy of this software and associated documentation
|
||||||
* files (the "Software"), to deal in the Software without
|
* files (the "Software"), to deal in the Software without
|
||||||
* restriction, including without limitation the rights to use, copy,
|
* restriction, including without limitation the rights to use, copy,
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
* of the Software, and to permit persons to whom the Software is
|
* of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be
|
* The above copyright notice and this permission notice shall be
|
||||||
* included in all copies or substantial portions of the Software.
|
* included in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <android_avb/avb_vbmeta_image.h>
|
#include <android_avb/avb_vbmeta_image.h>
|
||||||
#include <android_avb/avb_crypto.h>
|
#include <android_avb/avb_crypto.h>
|
||||||
#include <android_avb/avb_rsa.h>
|
#include <android_avb/avb_rsa.h>
|
||||||
#include <android_avb/avb_sha.h>
|
#include <android_avb/avb_sha.h>
|
||||||
#include <android_avb/avb_util.h>
|
#include <android_avb/avb_util.h>
|
||||||
#include <android_avb/avb_version.h>
|
#include <android_avb/avb_version.h>
|
||||||
|
|
||||||
AvbVBMetaVerifyResult avb_vbmeta_image_verify(
|
AvbVBMetaVerifyResult avb_vbmeta_image_verify(
|
||||||
const uint8_t* data,
|
const uint8_t* data,
|
||||||
size_t length,
|
size_t length,
|
||||||
const uint8_t** out_public_key_data,
|
const uint8_t** out_public_key_data,
|
||||||
size_t* out_public_key_length) {
|
size_t* out_public_key_length) {
|
||||||
AvbVBMetaVerifyResult ret;
|
AvbVBMetaVerifyResult ret;
|
||||||
AvbVBMetaImageHeader h;
|
AvbVBMetaImageHeader h;
|
||||||
uint8_t* computed_hash;
|
uint8_t* computed_hash;
|
||||||
const AvbAlgorithmData* algorithm;
|
const AvbAlgorithmData* algorithm;
|
||||||
AvbSHA256Ctx sha256_ctx;
|
AvbSHA256Ctx sha256_ctx;
|
||||||
AvbSHA512Ctx sha512_ctx;
|
AvbSHA512Ctx sha512_ctx;
|
||||||
const uint8_t* header_block;
|
const uint8_t* header_block;
|
||||||
const uint8_t* authentication_block;
|
const uint8_t* authentication_block;
|
||||||
const uint8_t* auxiliary_block;
|
const uint8_t* auxiliary_block;
|
||||||
int verification_result;
|
int verification_result;
|
||||||
|
|
||||||
ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
|
ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
|
||||||
|
|
||||||
if (out_public_key_data != NULL) {
|
if (out_public_key_data != NULL) {
|
||||||
*out_public_key_data = NULL;
|
*out_public_key_data = NULL;
|
||||||
}
|
}
|
||||||
if (out_public_key_length != NULL) {
|
if (out_public_key_length != NULL) {
|
||||||
*out_public_key_length = 0;
|
*out_public_key_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure magic is correct. */
|
/* Before we byteswap or compare Magic, ensure length is long enough. */
|
||||||
if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
|
if (length < sizeof(AvbVBMetaImageHeader)) {
|
||||||
avb_error("Magic is incorrect.\n");
|
avb_error("Length is smaller than header.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Before we byteswap, ensure length is long enough. */
|
/* Ensure magic is correct. */
|
||||||
if (length < sizeof(AvbVBMetaImageHeader)) {
|
if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
|
||||||
avb_error("Length is smaller than header.\n");
|
avb_error("Magic is incorrect.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
|
|
||||||
&h);
|
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.
|
/* 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)) {
|
if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
|
||||||
avb_error("Mismatch between image version and libavb version.\n");
|
(h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
|
||||||
ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
|
avb_error("Mismatch between image version and libavb version.\n");
|
||||||
goto out;
|
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') {
|
/* Ensure |release_string| ends with a NUL byte. */
|
||||||
avb_error("Release string does not end with a NUL byte.\n");
|
if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
|
||||||
goto out;
|
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 ||
|
/* Ensure inner block sizes are multiple of 64. */
|
||||||
(h.auxiliary_data_block_size & 0x3f) != 0) {
|
if ((h.authentication_data_block_size & 0x3f) != 0 ||
|
||||||
avb_error("Block size is not a multiple of 64.\n");
|
(h.auxiliary_data_block_size & 0x3f) != 0) {
|
||||||
goto out;
|
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);
|
/* Ensure block sizes all add up to at most |length|. */
|
||||||
if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
|
uint64_t block_total = sizeof(AvbVBMetaImageHeader);
|
||||||
!avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
|
if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
|
||||||
avb_error("Overflow while computing size of boot image.\n");
|
!avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
|
||||||
goto out;
|
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");
|
if (block_total > length) {
|
||||||
goto out;
|
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. */
|
uintptr_t data_ptr = (uintptr_t)data;
|
||||||
if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
|
/* Ensure passed in memory doesn't wrap. */
|
||||||
avb_error("Boot image location and length mismatch.\n");
|
if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
|
||||||
goto out;
|
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;
|
/* Ensure hash and signature are entirely in the Authentication data block. */
|
||||||
if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
|
uint64_t hash_end;
|
||||||
hash_end > h.authentication_data_block_size) {
|
if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
|
||||||
avb_error("Hash is not entirely in its block.\n");
|
hash_end > h.authentication_data_block_size) {
|
||||||
goto out;
|
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) ||
|
uint64_t signature_end;
|
||||||
signature_end > h.authentication_data_block_size) {
|
if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
|
||||||
avb_error("Signature is not entirely in its block.\n");
|
signature_end > h.authentication_data_block_size) {
|
||||||
goto out;
|
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;
|
/* Ensure public key is entirely in the Auxiliary data block. */
|
||||||
if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
|
uint64_t pubkey_end;
|
||||||
pubkey_end > h.auxiliary_data_block_size) {
|
if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
|
||||||
avb_error("Public key is not entirely in its block.\n");
|
pubkey_end > h.auxiliary_data_block_size) {
|
||||||
goto out;
|
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. */
|
/* Ensure public key metadata (if set) is entirely in the Auxiliary
|
||||||
if (h.public_key_metadata_size > 0) {
|
* data block. */
|
||||||
uint64_t pubkey_md_end;
|
if (h.public_key_metadata_size > 0) {
|
||||||
if (!avb_safe_add(&pubkey_md_end,
|
uint64_t pubkey_md_end;
|
||||||
h.public_key_metadata_offset,
|
if (!avb_safe_add(&pubkey_md_end,
|
||||||
h.public_key_metadata_size) ||
|
h.public_key_metadata_offset,
|
||||||
pubkey_md_end > h.auxiliary_data_block_size) {
|
h.public_key_metadata_size) ||
|
||||||
avb_error("Public key metadata is not entirely in its block.\n");
|
pubkey_md_end > h.auxiliary_data_block_size) {
|
||||||
goto out;
|
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) {
|
/* Bail early if there's no hash or signature. */
|
||||||
ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
|
if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
|
||||||
goto out;
|
ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
|
||||||
}
|
goto out;
|
||||||
|
}
|
||||||
/* Ensure algorithm field is supported. */
|
|
||||||
algorithm = avb_get_algorithm_data(h.algorithm_type);
|
/* Ensure algorithm field is supported. */
|
||||||
if (!algorithm) {
|
algorithm = avb_get_algorithm_data(h.algorithm_type);
|
||||||
avb_error("Invalid or unknown algorithm.\n");
|
if (!algorithm) {
|
||||||
goto out;
|
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) {
|
/* Bail if the embedded hash size doesn't match the chosen algorithm. */
|
||||||
avb_error("Embedded hash has wrong size.\n");
|
if (h.hash_size != algorithm->hash_len) {
|
||||||
goto out;
|
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.
|
/* 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);
|
header_block = data;
|
||||||
auxiliary_block = authentication_block + h.authentication_data_block_size;
|
authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
|
||||||
|
auxiliary_block = authentication_block + h.authentication_data_block_size;
|
||||||
switch (h.algorithm_type) {
|
|
||||||
/* Explicit fall-through: */
|
switch (h.algorithm_type) {
|
||||||
case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
|
/* Explicit fall-through: */
|
||||||
case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
|
case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
|
||||||
case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
|
case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
|
||||||
avb_sha256_init(&sha256_ctx);
|
case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
|
||||||
avb_sha256_update(
|
avb_sha256_init(&sha256_ctx);
|
||||||
&sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
|
avb_sha256_update(
|
||||||
avb_sha256_update(
|
&sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
|
||||||
&sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
|
avb_sha256_update(
|
||||||
computed_hash = avb_sha256_final(&sha256_ctx);
|
&sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
|
||||||
break;
|
computed_hash = avb_sha256_final(&sha256_ctx);
|
||||||
/* Explicit fall-through: */
|
break;
|
||||||
case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
|
/* Explicit fall-through: */
|
||||||
case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
|
case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
|
||||||
case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
|
case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
|
||||||
avb_sha512_init(&sha512_ctx);
|
case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
|
||||||
avb_sha512_update(
|
avb_sha512_init(&sha512_ctx);
|
||||||
&sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
|
avb_sha512_update(
|
||||||
avb_sha512_update(
|
&sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
|
||||||
&sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
|
avb_sha512_update(
|
||||||
computed_hash = avb_sha512_final(&sha512_ctx);
|
&sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
|
||||||
break;
|
computed_hash = avb_sha512_final(&sha512_ctx);
|
||||||
default:
|
break;
|
||||||
avb_error("Unknown algorithm.\n");
|
default:
|
||||||
goto out;
|
avb_error("Unknown algorithm.\n");
|
||||||
}
|
goto out;
|
||||||
|
}
|
||||||
if (avb_safe_memcmp(authentication_block + h.hash_offset,
|
|
||||||
computed_hash,
|
if (avb_safe_memcmp(authentication_block + h.hash_offset,
|
||||||
h.hash_size) != 0) {
|
computed_hash,
|
||||||
avb_error("Hash does not match!\n");
|
h.hash_size) != 0) {
|
||||||
ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
|
avb_error("Hash does not match!\n");
|
||||||
goto out;
|
ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
|
||||||
}
|
goto out;
|
||||||
|
}
|
||||||
verification_result =
|
|
||||||
avb_rsa_verify(auxiliary_block + h.public_key_offset,
|
verification_result =
|
||||||
h.public_key_size,
|
avb_rsa_verify(auxiliary_block + h.public_key_offset,
|
||||||
authentication_block + h.signature_offset,
|
h.public_key_size,
|
||||||
h.signature_size,
|
authentication_block + h.signature_offset,
|
||||||
authentication_block + h.hash_offset,
|
h.signature_size,
|
||||||
h.hash_size,
|
authentication_block + h.hash_offset,
|
||||||
algorithm->padding,
|
h.hash_size,
|
||||||
algorithm->padding_len);
|
algorithm->padding,
|
||||||
|
algorithm->padding_len);
|
||||||
if (verification_result == 0) {
|
|
||||||
ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
|
if (verification_result == 0) {
|
||||||
goto out;
|
ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
|
||||||
}
|
goto out;
|
||||||
|
}
|
||||||
if (h.public_key_size > 0) {
|
|
||||||
if (out_public_key_data != NULL) {
|
if (h.public_key_size > 0) {
|
||||||
*out_public_key_data = auxiliary_block + h.public_key_offset;
|
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;
|
if (out_public_key_length != NULL) {
|
||||||
}
|
*out_public_key_length = h.public_key_size;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ret = AVB_VBMETA_VERIFY_RESULT_OK;
|
|
||||||
|
ret = AVB_VBMETA_VERIFY_RESULT_OK;
|
||||||
out:
|
|
||||||
return ret;
|
out:
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
|
|
||||||
AvbVBMetaImageHeader* dest) {
|
void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
|
||||||
avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
|
AvbVBMetaImageHeader* dest) {
|
||||||
|
avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
|
||||||
dest->required_libavb_version_major =
|
|
||||||
avb_be32toh(dest->required_libavb_version_major);
|
dest->required_libavb_version_major =
|
||||||
dest->required_libavb_version_minor =
|
avb_be32toh(dest->required_libavb_version_major);
|
||||||
avb_be32toh(dest->required_libavb_version_minor);
|
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->authentication_data_block_size =
|
||||||
dest->auxiliary_data_block_size =
|
avb_be64toh(dest->authentication_data_block_size);
|
||||||
avb_be64toh(dest->auxiliary_data_block_size);
|
dest->auxiliary_data_block_size =
|
||||||
|
avb_be64toh(dest->auxiliary_data_block_size);
|
||||||
dest->algorithm_type = avb_be32toh(dest->algorithm_type);
|
|
||||||
|
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->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->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_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_offset =
|
||||||
dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
|
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->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 = avb_be64toh(dest->rollback_index);
|
||||||
}
|
dest->flags = avb_be32toh(dest->flags);
|
||||||
|
}
|
||||||
const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
|
|
||||||
const char* ret = NULL;
|
const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
|
||||||
|
const char* ret = NULL;
|
||||||
switch (result) {
|
|
||||||
case AVB_VBMETA_VERIFY_RESULT_OK:
|
switch (result) {
|
||||||
ret = "OK";
|
case AVB_VBMETA_VERIFY_RESULT_OK:
|
||||||
break;
|
ret = "OK";
|
||||||
case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
|
break;
|
||||||
ret = "OK_NOT_SIGNED";
|
case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
|
||||||
break;
|
ret = "OK_NOT_SIGNED";
|
||||||
case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
|
break;
|
||||||
ret = "INVALID_VBMETA_HEADER";
|
case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
|
||||||
break;
|
ret = "INVALID_VBMETA_HEADER";
|
||||||
case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
|
break;
|
||||||
ret = "UNSUPPORTED_VERSION";
|
case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
|
||||||
break;
|
ret = "UNSUPPORTED_VERSION";
|
||||||
case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
|
break;
|
||||||
ret = "HASH_MISMATCH";
|
case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
|
||||||
break;
|
ret = "HASH_MISMATCH";
|
||||||
case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
|
break;
|
||||||
ret = "SIGNATURE_MISMATCH";
|
case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
|
||||||
break;
|
ret = "SIGNATURE_MISMATCH";
|
||||||
/* Do not add a 'default:' case here because of -Wswitch. */
|
break;
|
||||||
}
|
/* Do not add a 'default:' case here because of -Wswitch. */
|
||||||
|
}
|
||||||
if (ret == NULL) {
|
|
||||||
avb_error("Unknown AvbVBMetaVerifyResult value.\n");
|
if (ret == NULL) {
|
||||||
ret = "(unknown)";
|
avb_error("Unknown AvbVBMetaVerifyResult value.\n");
|
||||||
}
|
ret = "(unknown)";
|
||||||
|
}
|
||||||
return ret;
|
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
/* The most recent unlock challenge generated. */
|
/* The most recent unlock challenge generated. */
|
||||||
static uint8_t last_unlock_challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
|
static uint8_t last_unlock_challenge[AVB_ATX_UNLOCK_CHALLENGE_SIZE];
|
||||||
|
static bool last_unlock_challenge_set = false;
|
||||||
|
|
||||||
/* Computes the SHA256 |hash| of |length| bytes of |data|. */
|
/* Computes the SHA256 |hash| of |length| bytes of |data|. */
|
||||||
static void sha256(const uint8_t* data,
|
static void sha256(const uint8_t* data,
|
||||||
|
|
@ -367,6 +368,7 @@ AvbIOResult avb_atx_generate_unlock_challenge(
|
||||||
avb_error("Failed to generate random challenge.\n");
|
avb_error("Failed to generate random challenge.\n");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
last_unlock_challenge_set = true;
|
||||||
out_unlock_challenge->version = 1;
|
out_unlock_challenge->version = 1;
|
||||||
sha256(permanent_attributes.product_id,
|
sha256(permanent_attributes.product_id,
|
||||||
AVB_ATX_PRODUCT_ID_SIZE,
|
AVB_ATX_PRODUCT_ID_SIZE,
|
||||||
|
|
@ -445,9 +447,16 @@ AvbIOResult avb_atx_validate_unlock_credential(
|
||||||
return AVB_IO_RESULT_OK;
|
return AVB_IO_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hash the most recent unlock challenge. */
|
||||||
|
if (!last_unlock_challenge_set) {
|
||||||
|
avb_error("Challenge does not exist.\n");
|
||||||
|
return AVB_IO_RESULT_OK;
|
||||||
|
}
|
||||||
|
sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash);
|
||||||
|
last_unlock_challenge_set = false;
|
||||||
|
|
||||||
/* Verify the challenge signature. */
|
/* Verify the challenge signature. */
|
||||||
algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
|
algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
|
||||||
sha512(last_unlock_challenge, AVB_ATX_UNLOCK_CHALLENGE_SIZE, challenge_hash);
|
|
||||||
if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
|
if (!avb_rsa_verify(unlock_credential->product_unlock_key_certificate
|
||||||
.signed_data.public_key,
|
.signed_data.public_key,
|
||||||
AVB_ATX_PUBLIC_KEY_SIZE,
|
AVB_ATX_PUBLIC_KEY_SIZE,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue