storage: flash_map: Add SHA-256 integrity method
Add SHA-256 flash integrity method. It reads flash data from a device giving an offset creating a SHA-256 hash to be compared with a reference. On sucess match, zero is returned, otherwise a negative errno value. Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
parent
9904022e77
commit
eb0f571790
7 changed files with 166 additions and 1 deletions
|
@ -75,6 +75,34 @@ struct flash_sector {
|
|||
size_t fs_size; /** flash sector size */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY)
|
||||
/**
|
||||
* @brief Structure for verify flash region integrity
|
||||
*
|
||||
* This is used to pass data to be used to check flash integrity using SHA-256
|
||||
* algorithm.
|
||||
*/
|
||||
struct flash_area_check {
|
||||
const uint8_t *match; /** 256 bits match vector */
|
||||
size_t clen; /** Content len to be compared */
|
||||
size_t off; /** Start Offset */
|
||||
uint8_t *rbuf; /** Temporary read buffer */
|
||||
size_t rblen; /** Size of read buffer */
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify flash memory length bytes integrity from a flash area. The start
|
||||
* point is indicated by an offset value.
|
||||
*
|
||||
* @param[in] fa Flash area
|
||||
* @param[in] fic Flash area check integrity data
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail
|
||||
*/
|
||||
int flash_area_check_int_sha256(const struct flash_area *fa,
|
||||
const struct flash_area_check *fac);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Retrieve partitions flash area from the flash_map.
|
||||
*
|
||||
|
|
|
@ -28,4 +28,12 @@ config FLASH_MAP_CUSTOM
|
|||
User must provide such a description in place of default on
|
||||
if had enabled this option.
|
||||
|
||||
config FLASH_AREA_CHECK_INTEGRITY
|
||||
bool "Enable flash check functions"
|
||||
select TINYCRYPT
|
||||
select TINYCRYPT_SHA256
|
||||
help
|
||||
If enabled, there will be available the backend to check flash
|
||||
integrity using SHA-256 verification algorithm.
|
||||
|
||||
endif
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015 Runtime Inc
|
||||
* Copyright (c) 2017 Linaro Ltd
|
||||
* Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -15,6 +16,12 @@
|
|||
#include <soc.h>
|
||||
#include <init.h>
|
||||
|
||||
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY)
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/sha256.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
|
||||
struct layout_data {
|
||||
uint32_t area_idx;
|
||||
|
@ -262,3 +269,60 @@ const struct device *flash_area_get_device(const struct flash_area *fa)
|
|||
{
|
||||
return device_get_binding(fa->fa_dev_name);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY)
|
||||
int flash_area_check_int_sha256(const struct flash_area *fa,
|
||||
const struct flash_area_check *fac)
|
||||
{
|
||||
unsigned char hash[TC_SHA256_DIGEST_SIZE];
|
||||
struct tc_sha256_state_struct sha;
|
||||
struct device *dev;
|
||||
int to_read;
|
||||
int pos;
|
||||
int rc;
|
||||
|
||||
if (!fa || !fac || !fac->match || !fac->rbuf ||
|
||||
fac->clen <= 0 || fac->off < 0 || fac->rblen <= 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!is_in_flash_area_bounds(fa, fac->off, fac->clen)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tc_sha256_init(&sha) != TC_CRYPTO_SUCCESS) {
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
dev = device_get_binding(fa->fa_dev_name);
|
||||
to_read = fac->rblen;
|
||||
|
||||
for (pos = 0; pos < fac->clen; pos += to_read) {
|
||||
if (pos + to_read > fac->clen) {
|
||||
to_read = fac->clen - pos;
|
||||
}
|
||||
|
||||
rc = flash_read(dev, (fa->fa_off + fac->off + pos),
|
||||
fac->rbuf, to_read);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (tc_sha256_update(&sha,
|
||||
fac->rbuf,
|
||||
to_read) != TC_CRYPTO_SUCCESS) {
|
||||
return -ESRCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (tc_sha256_final(hash, &sha) != TC_CRYPTO_SUCCESS) {
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
if (memcmp(hash, fac->match, TC_SHA256_DIGEST_SIZE)) {
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FLASH_AREA_CHECK_INTEGRITY */
|
||||
|
|
|
@ -2,3 +2,4 @@ CONFIG_ZTEST=y
|
|||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_FLASH_AREA_CHECK_INTEGRITY=y
|
||||
|
|
|
@ -2,3 +2,4 @@ CONFIG_ZTEST=y
|
|||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_FLASH_AREA_CHECK_INTEGRITY=y
|
||||
|
|
|
@ -2,3 +2,4 @@ CONFIG_ZTEST=y
|
|||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_FLASH_AREA_CHECK_INTEGRITY=y
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015 Runtime Inc
|
||||
* Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -98,9 +99,70 @@ void test_flash_area_get_sectors(void)
|
|||
|
||||
}
|
||||
|
||||
void test_flash_area_check_int_sha256(void)
|
||||
{
|
||||
/* echo $'0123456789abcdef\nfedcba98765432' > tst.sha
|
||||
* hexdump tst.sha
|
||||
*/
|
||||
uint8_t tst_vec[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
||||
0x0a, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x39,
|
||||
0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x0a };
|
||||
/* sha256sum tst.sha */
|
||||
uint8_t tst_sha[] = { 0x28, 0xf1, 0x6e, 0xea, 0xc3, 0xea, 0x89, 0x8d,
|
||||
0x80, 0x9e, 0x98, 0xeb, 0x09, 0x49, 0x98, 0x08,
|
||||
0x40, 0x69, 0x43, 0xa6, 0xef, 0xe1, 0xa3, 0xf9,
|
||||
0x3d, 0xdf, 0x15, 0x9e, 0x06, 0xf8, 0xdd, 0xbd };
|
||||
|
||||
const struct flash_area *fa;
|
||||
struct flash_area_check fac = { NULL, 0, -1, NULL, 0 };
|
||||
uint8_t buffer[16];
|
||||
int rc;
|
||||
|
||||
rc = flash_area_open(FLASH_AREA_ID(image_1), &fa);
|
||||
zassert_true(rc == 0, "flash_area_open() fail, error %d\n", rc);
|
||||
rc = flash_area_erase(fa, 0, fa->fa_size);
|
||||
zassert_true(rc == 0, "Flash erase failure (%d), error %d\n", rc);
|
||||
rc = flash_area_write(fa, 0, tst_vec, sizeof(tst_vec));
|
||||
zassert_true(rc == 0, "Flash img write, error %d\n", rc);
|
||||
|
||||
rc = flash_area_check_int_sha256(NULL, NULL);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 params 1, 2\n");
|
||||
rc = flash_area_check_int_sha256(NULL, &fac);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 params 2\n");
|
||||
rc = flash_area_check_int_sha256(fa, NULL);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 params 1\n");
|
||||
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 fac match\n");
|
||||
fac.match = tst_sha;
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 fac clen\n");
|
||||
fac.clen = sizeof(tst_vec);
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 fac off\n");
|
||||
fac.off = 0;
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 fac rbuf\n");
|
||||
fac.rbuf = buffer;
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_true(rc == -EINVAL, "Flash area check int 256 fac rblen\n");
|
||||
fac.rblen = sizeof(buffer);
|
||||
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_true(rc == 0, "Flash area check int 256 OK, error %d\n", rc);
|
||||
tst_sha[0] = 0x00;
|
||||
rc = flash_area_check_int_sha256(fa, &fac);
|
||||
zassert_false(rc == 0, "Flash area check int 256 wrong sha\n");
|
||||
|
||||
flash_area_close(fa);
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(test_flash_map,
|
||||
ztest_unit_test(test_flash_area_get_sectors));
|
||||
ztest_unit_test(test_flash_area_get_sectors),
|
||||
ztest_unit_test(test_flash_area_check_int_sha256)
|
||||
);
|
||||
ztest_run_test_suite(test_flash_map);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue