mgmt: updatehub: Rework check integrity

The TinyCrypt is the current library used by UpdateHub to perform
SHA-256 integrity check. This refactor code and add support to
mbedTLS library. It changes default library to mbedTLS to use
hardware accelerator when available.

Signed-off-by: Gerson Fernando Budke <gerson.budke@ossystems.com.br>
This commit is contained in:
Gerson Fernando Budke 2022-12-31 13:50:50 +01:00 committed by Fabio Baltieri
commit 313049e325
5 changed files with 186 additions and 21 deletions

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2018 O.S.Systems
# Copyright (c) 2018-2023 O.S.Systems
#
# SPDX -License-Identifier: Apache-2.0
#
@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_device.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_firmware.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_timer.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_integrity.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB_SHELL shell.c)
zephyr_include_directories(

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018-2020 O.S.Systems
# Copyright (c) 2018-2023 O.S.Systems
# SPDX -License-Identifier: Apache-2.0
menuconfig UPDATEHUB
@ -17,8 +17,6 @@ menuconfig UPDATEHUB
select COAP
select DNS_RESOLVER
select JSON_LIBRARY
select TINYCRYPT
select TINYCRYPT_SHA256
select HWINFO
help
UpdateHub is an enterprise-grade solution which makes simple to
@ -149,6 +147,10 @@ config UPDATEHUB_DOWNLOAD_STORAGE_SHA256_VERIFICATION
endchoice
choice FLASH_AREA_CHECK_INTEGRITY_BACKEND
default FLASH_AREA_CHECK_INTEGRITY_MBEDTLS
endchoice
module = UPDATEHUB
module-str = Log level for UpdateHub
module-help = Enables logging for UpdateHub code.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020 O.S.Systems
* Copyright (c) 2018-2023 O.S.Systems
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -18,7 +18,6 @@ LOG_MODULE_REGISTER(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);
#include <zephyr/net/dns_resolve.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/sys/reboot.h>
#include <tinycrypt/sha256.h>
#include <zephyr/data/json.h>
#include <zephyr/storage/flash_map.h>
@ -27,6 +26,7 @@ LOG_MODULE_REGISTER(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);
#include "updatehub_firmware.h"
#include "updatehub_device.h"
#include "updatehub_timer.h"
#include "updatehub_integrity.h"
#if defined(CONFIG_UPDATEHUB_DTLS)
#define CA_CERTIFICATE_TAG 1
@ -45,8 +45,6 @@ LOG_MODULE_REGISTER(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);
#define MAX_DOWNLOAD_DATA (MAX_PAYLOAD_SIZE + 32)
#define MAX_IP_SIZE 30
#define SHA256_HEX_DIGEST_SIZE ((TC_SHA256_DIGEST_SIZE * 2) + 1)
#if defined(CONFIG_UPDATEHUB_CE)
#define UPDATEHUB_SERVER CONFIG_UPDATEHUB_SERVER
#else
@ -66,9 +64,9 @@ static struct updatehub_context {
struct coap_block_context block;
struct k_sem semaphore;
struct flash_img_context flash_ctx;
struct tc_sha256_state_struct sha256sum;
struct updatehub_crypto_context crypto_ctx;
enum updatehub_response code_status;
uint8_t hash[TC_SHA256_DIGEST_SIZE];
uint8_t hash[SHA256_BIN_DIGEST_SIZE];
uint8_t uri_path[MAX_PATH_SIZE];
uint8_t payload[MAX_PAYLOAD_SIZE];
int downloaded_size;
@ -118,21 +116,21 @@ static void prepare_fds(void)
static int metadata_hash_get(char *metadata)
{
struct tc_sha256_state_struct sha256sum;
struct updatehub_crypto_context local_crypto_ctx;
if (tc_sha256_init(&sha256sum) == 0) {
if (updatehub_integrity_init(&local_crypto_ctx)) {
return -1;
}
if (tc_sha256_update(&sha256sum, metadata, strlen(metadata)) == 0) {
if (updatehub_integrity_update(&local_crypto_ctx, metadata, strlen(metadata))) {
return -1;
}
if (tc_sha256_final(ctx.hash, &sha256sum) == 0) {
if (updatehub_integrity_finish(&local_crypto_ctx, ctx.hash, sizeof(ctx.hash))) {
return -1;
}
if (bin2hex_str(ctx.hash, TC_SHA256_DIGEST_SIZE,
if (bin2hex_str(ctx.hash, SHA256_BIN_DIGEST_SIZE,
update_info.package_uid, SHA256_HEX_DIGEST_SIZE)) {
return -1;
}
@ -367,12 +365,12 @@ static bool install_update_cb_sha256(void)
{
char sha256[SHA256_HEX_DIGEST_SIZE];
if (tc_sha256_final(ctx.hash, &ctx.sha256sum) < 1) {
if (updatehub_integrity_finish(&ctx.crypto_ctx, ctx.hash, sizeof(ctx.hash))) {
LOG_ERR("Could not finish sha256sum");
return false;
}
if (bin2hex_str(ctx.hash, TC_SHA256_DIGEST_SIZE,
if (bin2hex_str(ctx.hash, SHA256_BIN_DIGEST_SIZE,
sha256, SHA256_HEX_DIGEST_SIZE)) {
LOG_ERR("Could not create sha256sum hex representation");
return false;
@ -461,9 +459,9 @@ static void install_update_cb(void)
ctx.downloaded_size = ctx.downloaded_size + payload_len;
#ifdef _DOWNLOAD_SHA256_VERIFICATION
if (tc_sha256_update(&ctx.sha256sum,
if (updatehub_integrity_update(&ctx.crypto_ctx,
payload_start,
payload_len) < 1) {
payload_len)) {
LOG_ERR("Could not update sha256sum");
ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR;
goto cleanup;
@ -506,7 +504,7 @@ static void install_update_cb(void)
#else
if (hex2bin(update_info.sha256sum_image,
SHA256_HEX_DIGEST_SIZE - 1, ctx.hash,
TC_SHA256_DIGEST_SIZE) != TC_SHA256_DIGEST_SIZE) {
SHA256_BIN_DIGEST_SIZE) != SHA256_BIN_DIGEST_SIZE) {
LOG_ERR("Firmware - metadata validation has failed");
ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR;
goto cleanup;
@ -541,7 +539,7 @@ static enum updatehub_response install_update(void)
}
#ifdef _DOWNLOAD_SHA256_VERIFICATION
if (tc_sha256_init(&ctx.sha256sum) < 1) {
if (updatehub_integrity_init(&ctx.crypto_ctx)) {
LOG_ERR("Could not start sha256sum");
ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR;
goto error;

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2023 O.S.Systems
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);
#include "updatehub_integrity.h"
int updatehub_integrity_init(struct updatehub_crypto_context *ctx)
{
int ret;
if (ctx == NULL) {
LOG_DBG("Invalid integrity context");
return -EINVAL;
}
memset(ctx, 0, sizeof(struct updatehub_crypto_context));
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS)
ctx->md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (ctx->md_info == NULL) {
LOG_DBG("Message Digest not found or not enabled");
return -ENOENT;
}
mbedtls_md_init(&ctx->md_ctx);
ret = mbedtls_md_setup(&ctx->md_ctx, ctx->md_info, 0);
if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) {
LOG_DBG("Bad Message Digest selected");
return -EFAULT;
}
if (ret == MBEDTLS_ERR_MD_ALLOC_FAILED) {
LOG_DBG("Failed to allocate memory");
return -ENOMEM;
}
ret = mbedtls_md_starts(&ctx->md_ctx);
if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) {
LOG_DBG("Bad Message Digest selected");
return -EFAULT;
}
#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
ret = tc_sha256_init(&ctx->sha256sum);
if (ret != TC_CRYPTO_SUCCESS) {
LOG_DBG("Invalid integrity context");
return -EFAULT;
}
#endif
return 0;
}
int updatehub_integrity_update(struct updatehub_crypto_context *ctx,
const uint8_t *buffer, const uint32_t len)
{
int ret;
if (ctx == NULL || buffer == NULL) {
return -EINVAL;
}
/* bypass */
if (len == 0) {
return 0;
}
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS)
ret = mbedtls_md_update(&ctx->md_ctx, buffer, len);
if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) {
LOG_DBG("Bad Message Digest selected");
return -EFAULT;
}
#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
ret = tc_sha256_update(&ctx->sha256sum, buffer, len);
if (ret != TC_CRYPTO_SUCCESS) {
LOG_DBG("Invalid integrity context or invalid buffer");
return -EFAULT;
}
#endif
return 0;
}
int updatehub_integrity_finish(struct updatehub_crypto_context *ctx,
uint8_t *hash, const uint32_t size)
{
int ret;
if (ctx == NULL || hash == NULL) {
return -EINVAL;
}
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS)
if (size < mbedtls_md_get_size(ctx->md_info)) {
LOG_DBG("HASH input buffer is to small to store the message digest");
return -EINVAL;
}
ret = mbedtls_md_finish(&ctx->md_ctx, hash);
if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) {
LOG_DBG("Bad Message Digest selected");
return -EFAULT;
}
mbedtls_md_free(&ctx->md_ctx);
#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
ret = tc_sha256_final(hash, &ctx->sha256sum);
if (ret != TC_CRYPTO_SUCCESS) {
LOG_DBG("Invalid integrity context or invalid hash pointer");
return -EFAULT;
}
#endif
return 0;
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 O.S.Systems
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __UPDATEHUB_INTEGRITY_H__
#define __UPDATEHUB_INTEGRITY_H__
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS)
#include <mbedtls/md.h>
#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
#include <tinycrypt/sha256.h>
#include <tinycrypt/constants.h>
#else
#error "Integrity check method not defined"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define SHA256_BIN_DIGEST_SIZE (32)
#define SHA256_HEX_DIGEST_SIZE ((SHA256_BIN_DIGEST_SIZE * 2) + 1)
struct updatehub_crypto_context {
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS)
mbedtls_md_context_t md_ctx;
const mbedtls_md_info_t *md_info;
#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
struct tc_sha256_state_struct sha256sum;
#endif
};
int updatehub_integrity_init(struct updatehub_crypto_context *ctx);
int updatehub_integrity_update(struct updatehub_crypto_context *ctx,
const uint8_t *buffer, const uint32_t len);
int updatehub_integrity_finish(struct updatehub_crypto_context *ctx,
uint8_t *hash, const uint32_t size);
#ifdef __cplusplus
}
#endif
#endif /* __UPDATEHUB_INTEGRITY_H__ */