From b1e0b11cc9e8a850a8e479927432068ce62a815a Mon Sep 17 00:00:00 2001 From: Lionel Debieve Date: Mon, 26 Aug 2019 15:14:51 +0200 Subject: crypto: stm32_hash: Add HASH driver The driver manages the HASH processor IP on STM32MP1 Signed-off-by: Lionel Debieve Change-Id: I3b67c80c16d819f86b951dae29a6c465e51ad585 --- drivers/st/crypto/stm32_hash.c | 330 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 drivers/st/crypto/stm32_hash.c (limited to 'drivers') diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c new file mode 100644 index 00000000..f72787d3 --- /dev/null +++ b/drivers/st/crypto/stm32_hash.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DT_HASH_COMPAT "st,stm32f756-hash" + +#define HASH_CR 0x00U +#define HASH_DIN 0x04U +#define HASH_STR 0x08U +#define HASH_SR 0x24U +#define HASH_HREG(x) (0x310U + ((x) * 0x04U)) + +/* Control Register */ +#define HASH_CR_INIT BIT(2) +#define HASH_CR_DATATYPE_SHIFT U(4) + +#define HASH_CR_ALGO_SHA1 0x0U +#define HASH_CR_ALGO_MD5 BIT(7) +#define HASH_CR_ALGO_SHA224 BIT(18) +#define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) + +/* Status Flags */ +#define HASH_SR_DCIS BIT(1) +#define HASH_SR_BUSY BIT(3) + +/* STR Register */ +#define HASH_STR_NBLW_MASK GENMASK(4, 0) +#define HASH_STR_DCAL BIT(8) + +#define MD5_DIGEST_SIZE 16U +#define SHA1_DIGEST_SIZE 20U +#define SHA224_DIGEST_SIZE 28U +#define SHA256_DIGEST_SIZE 32U + +#define HASH_TIMEOUT_US 10000U + +enum stm32_hash_data_format { + HASH_DATA_32_BITS, + HASH_DATA_16_BITS, + HASH_DATA_8_BITS, + HASH_DATA_1_BIT +}; + +struct stm32_hash_instance { + uintptr_t base; + unsigned int clock; + size_t digest_size; +}; + +struct stm32_hash_remain { + uint32_t buffer; + size_t length; +}; + +/* Expect a single HASH peripheral */ +static struct stm32_hash_instance stm32_hash; +static struct stm32_hash_remain stm32_remain; + +static uintptr_t hash_base(void) +{ + return stm32_hash.base; +} + +static int hash_wait_busy(void) +{ + uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); + + while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int hash_wait_computation(void) +{ + uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); + + while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int hash_write_data(uint32_t data) +{ + int ret; + + ret = hash_wait_busy(); + if (ret != 0) { + return ret; + } + + mmio_write_32(hash_base() + HASH_DIN, data); + + return 0; +} + +static void hash_hw_init(enum stm32_hash_algo_mode mode) +{ + uint32_t reg; + + reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); + + switch (mode) { + case HASH_MD5SUM: + reg |= HASH_CR_ALGO_MD5; + stm32_hash.digest_size = MD5_DIGEST_SIZE; + break; + case HASH_SHA1: + reg |= HASH_CR_ALGO_SHA1; + stm32_hash.digest_size = SHA1_DIGEST_SIZE; + break; + case HASH_SHA224: + reg |= HASH_CR_ALGO_SHA224; + stm32_hash.digest_size = SHA224_DIGEST_SIZE; + break; + /* Default selected algo is SHA256 */ + case HASH_SHA256: + default: + reg |= HASH_CR_ALGO_SHA256; + stm32_hash.digest_size = SHA256_DIGEST_SIZE; + break; + } + + mmio_write_32(hash_base() + HASH_CR, reg); +} + +static int hash_get_digest(uint8_t *digest) +{ + int ret; + uint32_t i; + uint32_t dsg; + + ret = hash_wait_computation(); + if (ret != 0) { + return ret; + } + + for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) { + dsg = __builtin_bswap32(mmio_read_32(hash_base() + + HASH_HREG(i))); + memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t)); + } + +#if defined(IMAGE_BL2) + /* + * Clean hardware context as HASH could be used later + * by non-secure software + */ + hash_hw_init(HASH_SHA256); +#endif + return 0; +} + +int stm32_hash_update(const uint8_t *buffer, size_t length) +{ + size_t remain_length = length; + int ret = 0; + + if ((length == 0U) || (buffer == NULL)) { + return 0; + } + + stm32mp_clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + uint32_t copysize; + + copysize = MIN((sizeof(uint32_t) - stm32_remain.length), + length); + memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length, + buffer, copysize); + remain_length -= copysize; + buffer += copysize; + if (stm32_remain.length == sizeof(uint32_t)) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { + goto exit; + } + + zeromem(&stm32_remain, sizeof(stm32_remain)); + } + } + + while (remain_length / sizeof(uint32_t) != 0U) { + uint32_t tmp_buf; + + memcpy(&tmp_buf, buffer, sizeof(uint32_t)); + ret = hash_write_data(tmp_buf); + if (ret != 0) { + goto exit; + } + + buffer += sizeof(uint32_t); + remain_length -= sizeof(uint32_t); + } + + if (remain_length != 0U) { + assert(stm32_remain.length == 0U); + + memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length); + stm32_remain.length = remain_length; + } + +exit: + stm32mp_clk_disable(stm32_hash.clock); + + return ret; +} + +int stm32_hash_final(uint8_t *digest) +{ + int ret; + + stm32mp_clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { + stm32mp_clk_disable(stm32_hash.clock); + return ret; + } + + mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, + 8U * stm32_remain.length); + zeromem(&stm32_remain, sizeof(stm32_remain)); + } + + mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); + + ret = hash_get_digest(digest); + + stm32mp_clk_disable(stm32_hash.clock); + + return ret; +} + +int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, + uint8_t *digest) +{ + int ret; + + ret = stm32_hash_update(buffer, length); + if (ret != 0) { + return ret; + } + + return stm32_hash_final(digest); +} + +void stm32_hash_init(enum stm32_hash_algo_mode mode) +{ + stm32mp_clk_enable(stm32_hash.clock); + + hash_hw_init(mode); + + stm32mp_clk_disable(stm32_hash.clock); + + zeromem(&stm32_remain, sizeof(stm32_remain)); +} + +int stm32_hash_register(void) +{ + struct dt_node_info hash_info; + int node; + + for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT); + node != -FDT_ERR_NOTFOUND; + node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) { +#if defined(IMAGE_BL2) + if (hash_info.status != DT_DISABLED) { + break; + } +#else + if (hash_info.status == DT_SECURE) { + break; + } +#endif + } + + if (node == -FDT_ERR_NOTFOUND) { + return -ENODEV; + } + + if (hash_info.clock < 0) { + return -EINVAL; + } + + stm32_hash.base = hash_info.base; + stm32_hash.clock = hash_info.clock; + + stm32mp_clk_enable(stm32_hash.clock); + + if (hash_info.reset >= 0) { + stm32mp_reset_assert((unsigned long)hash_info.reset); + udelay(20); + stm32mp_reset_deassert((unsigned long)hash_info.reset); + } + + stm32mp_clk_disable(stm32_hash.clock); + + return 0; +} -- cgit v1.2.3 From f700423c1f2426ca3c5ccb9ee4e765743424b074 Mon Sep 17 00:00:00 2001 From: Lionel Debieve Date: Mon, 16 Sep 2019 12:17:09 +0200 Subject: bsec: move bsec_mode_is_closed_device() service to platform This BSEC service is a platform specific service. Implementation moved to the platform part. Signed-off-by: Lionel Debieve Change-Id: I1f70ed48a446860498ed111acce01187568538c9 --- drivers/st/bsec/bsec.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c index b3c15ee8..01c369ed 100644 --- a/drivers/st/bsec/bsec.c +++ b/drivers/st/bsec/bsec.c @@ -840,22 +840,6 @@ static uint32_t bsec_power_safmem(bool power) return BSEC_OK; } -/* - * bsec_mode_is_closed_device: read OTP secure sub-mode. - * return: false if open_device and true of closed_device. - */ -bool bsec_mode_is_closed_device(void) -{ - uint32_t value; - - if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) || - (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) { - return true; - } - - return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED; -} - /* * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value * otp_value: read value. @@ -894,7 +878,7 @@ uint32_t bsec_check_nsec_access_rights(uint32_t otp) if (otp >= STM32MP1_UPPER_OTP_START) { /* Check if BSEC is in OTP-SECURED closed_device state. */ - if (bsec_mode_is_closed_device()) { + if (stm32mp_is_closed_device()) { if (!non_secure_can_access(otp)) { return BSEC_ERROR; } -- cgit v1.2.3 From 4bdb1a7a6a1325343b0f0c375b43e9b874e31fca Mon Sep 17 00:00:00 2001 From: Lionel Debieve Date: Tue, 3 Sep 2019 12:22:23 +0200 Subject: stm32mp1: add authentication support for stm32image This commit adds authentication binary support for STM32MP1. It prints the bootrom authentication result if signed image is used and authenticates the next loaded STM32 images. It also enables the dynamic translation table support (PLAT_XLAT_TABLES_DYNAMIC) to use bootrom services. Signed-off-by: Lionel Debieve Change-Id: Iba706519e0dc6b6fae1f3dd498383351f0f75f51 --- drivers/st/io/io_stm32image.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c index 971dcce5..413521b1 100644 --- a/drivers/st/io/io_stm32image.c +++ b/drivers/st/io/io_stm32image.c @@ -246,7 +246,7 @@ static int stm32image_partition_size(io_entity_t *entity, size_t *length) static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, size_t length, size_t *length_read) { - int result = 0; + int result; uint8_t *local_buffer = (uint8_t *)buffer; boot_api_image_header_t *header = (boot_api_image_header_t *)first_lba_buffer; @@ -341,6 +341,12 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, header->magic = 0; } + result = stm32mp_auth_image(header, buffer); + if (result != 0) { + ERROR("Authentication Failed (%i)\n", result); + return result; + } + io_close(backend_handle); } -- cgit v1.2.3