mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 10:04:26 +00:00
Merge changes from topic "stm32mp1-trusted-boot" into integration
* changes: docs(st): update documentation for TRUSTED_BOARD_BOOT fix(build): ensure that the correct rule is called for tools feat(stm32mp1): add the platform specific build for tools fix(stm32mp13-fdts): remove secure status feat(stm32mp1-fdts): add CoT and fuse references for authentication feat(stm32mp1): add a check on TRUSTED_BOARD_BOOT with secure chip feat(stm32mp1): add the decryption support feat(stm32mp1): add the TRUSTED_BOARD_BOOT support feat(stm32mp1): update ROM code API for header v2 management feat(stm32mp1): remove unused function from boot API refactor(stm32mp1): remove authentication using STM32 image mode fix(fconf): fix type error displaying disable_auth feat(tbbr): increase PK_DER_LEN size fix(auth): correct sign-compare warning feat(auth): allow to verify PublicKey with platform format PK feat(cert-create): update for ECDSA brainpoolP256r/t1 support feat(stm32mp1): add RNG initialization in BL2 for STM32MP13 feat(st-crypto): remove BL32 HASH driver usage feat(stm32mp1): add a stm32mp crypto library feat(st-crypto): add STM32 RNG driver feat(st-crypto): add AES decrypt/auth by SAES IP feat(st-crypto): add ECDSA signature check with PKA feat(st-crypto): update HASH for new hardware version used in STM32MP13
This commit is contained in:
commit
c3170fd80b
49 changed files with 3856 additions and 228 deletions
6
Makefile
6
Makefile
|
@ -1470,7 +1470,7 @@ checkpatch: locate-checkpatch
|
|||
certtool: ${CRTTOOL}
|
||||
|
||||
${CRTTOOL}: FORCE
|
||||
${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${CRTTOOLPATH}
|
||||
${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${CRTTOOLPATH} all
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@${ECHO_BLANK_LINE}
|
||||
|
@ -1515,7 +1515,7 @@ fwu_fip: ${BUILD_PLAT}/${FWU_FIP_NAME}
|
|||
|
||||
${FIPTOOL}: FORCE
|
||||
ifdef UNIX_MK
|
||||
${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} OPENSSL_DIR=${OPENSSL_DIR} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${FIPTOOLPATH}
|
||||
${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} OPENSSL_DIR=${OPENSSL_DIR} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${FIPTOOLPATH} all
|
||||
else
|
||||
# Clear the MAKEFLAGS as we do not want
|
||||
# to pass the gnumake flags to nmake.
|
||||
|
@ -1536,7 +1536,7 @@ doc:
|
|||
enctool: ${ENCTOOL}
|
||||
|
||||
${ENCTOOL}: FORCE
|
||||
${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${ENCTOOLPATH}
|
||||
${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${ENCTOOLPATH} all
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@${ECHO_BLANK_LINE}
|
||||
|
|
|
@ -67,6 +67,11 @@ after which it will be removed.
|
|||
+================================+=============+=========+=========================================================+
|
||||
| STM32MP_USE_STM32IMAGE macro | Dec '21 | 2.7 | FIP is the recommended boot method for STM32MP |
|
||||
+--------------------------------+-------------+---------+---------------------------------------------------------+
|
||||
| plat_convert_pk() function | Nov'22 | Next | Platform conversion to manage specific PK hash |
|
||||
| | | release | |
|
||||
| | | after | |
|
||||
| | | 2.8 | |
|
||||
+--------------------------------+-------------+---------+---------------------------------------------------------+
|
||||
|
||||
--------------
|
||||
|
||||
|
|
|
@ -610,22 +610,28 @@ Common build options
|
|||
|
||||
- ``KEY_ALG``: This build flag enables the user to select the algorithm to be
|
||||
used for generating the PKCS keys and subsequent signing of the certificate.
|
||||
It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option
|
||||
``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR
|
||||
compliant and is retained only for compatibility. The default value of this
|
||||
flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme.
|
||||
It accepts 5 values: ``rsa``, ``rsa_1_5``, ``ecdsa``, ``ecdsa-brainpool-regular``
|
||||
and ``ecdsa-brainpool-twisted``. The option ``rsa_1_5`` is the legacy PKCS#1
|
||||
RSA 1.5 algorithm which is not TBBR compliant and is retained only for
|
||||
compatibility. The default value of this flag is ``rsa`` which is the TBBR
|
||||
compliant PKCS#1 RSA 2.1 scheme.
|
||||
|
||||
- ``KEY_SIZE``: This build flag enables the user to select the key size for
|
||||
the algorithm specified by ``KEY_ALG``. The valid values for ``KEY_SIZE``
|
||||
depend on the chosen algorithm and the cryptographic module.
|
||||
|
||||
+-----------+------------------------------------+
|
||||
| KEY_ALG | Possible key sizes |
|
||||
+===========+====================================+
|
||||
| rsa | 1024 , 2048 (default), 3072, 4096* |
|
||||
+-----------+------------------------------------+
|
||||
| ecdsa | unavailable |
|
||||
+-----------+------------------------------------+
|
||||
+---------------------------+------------------------------------+
|
||||
| KEY_ALG | Possible key sizes |
|
||||
+===========================+====================================+
|
||||
| rsa | 1024 , 2048 (default), 3072, 4096* |
|
||||
+---------------------------+------------------------------------+
|
||||
| ecdsa | unavailable |
|
||||
+---------------------------+------------------------------------+
|
||||
| ecdsa-brainpool-regular | unavailable |
|
||||
+---------------------------+------------------------------------+
|
||||
| ecdsa-brainpool-twisted | unavailable |
|
||||
+---------------------------+------------------------------------+
|
||||
|
||||
|
||||
* Only 2048 bits size is available with CryptoCell 712 SBROM release 1.
|
||||
Only 3072 bits size is available with CryptoCell 712 SBROM release 2.
|
||||
|
|
|
@ -809,6 +809,34 @@ The function returns 0 on success. Any other value means the counter value
|
|||
either could not be updated or the authentication image descriptor indicates
|
||||
that it is not allowed to be updated.
|
||||
|
||||
Function: plat_convert_pk()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
Argument : void *, unsigned int, void **, unsigned int *
|
||||
Return : int
|
||||
|
||||
This function is optional when Trusted Board Boot is enabled, and only
|
||||
used if the platform saves a hash of the ROTPK.
|
||||
First argument is the Distinguished Encoding Rules (DER) ROTPK.
|
||||
Second argument is its size.
|
||||
Third argument is used to return a pointer to a buffer, which hash should
|
||||
be the one saved in OTP.
|
||||
Fourth argument is a pointer to return its size.
|
||||
|
||||
Most platforms save the hash of the ROTPK, but some may save slightly different
|
||||
information - e.g the hash of the ROTPK plus some related information.
|
||||
Defining this function allows to transform the ROTPK used to verify
|
||||
the signature to the buffer (a platform specific public key) which
|
||||
hash is saved in OTP.
|
||||
|
||||
The default implementation copies the input key and length to the output without
|
||||
modification.
|
||||
|
||||
The function returns 0 on success. Any other value means the expected
|
||||
public key buffer cannot be extracted.
|
||||
|
||||
Dynamic Root of Trust for Measurement support (in BL31)
|
||||
-------------------------------------------------------
|
||||
|
||||
|
|
|
@ -235,6 +235,40 @@ With OP-TEE:
|
|||
BL32_EXTRA2=<optee_directory>/tee-pageable_v2.bin
|
||||
fip
|
||||
|
||||
Trusted Boot Board
|
||||
__________________
|
||||
|
||||
.. code:: shell
|
||||
|
||||
tools/cert_create/cert_create -n --rot-key "build/stm32mp1/debug/rot_key.pem" \
|
||||
--tfw-nvctr 0 \
|
||||
--ntfw-nvctr 0 \
|
||||
--key-alg ecdsa --hash-alg sha256 \
|
||||
--trusted-key-cert build/stm32mp1/cert_images/trusted-key-cert.key-crt \
|
||||
--tos-fw <optee_directory>/tee-header_v2.bin \
|
||||
--tos-fw-extra1 <optee_directory>/tee-pager_v2.bin \
|
||||
--tos-fw-extra2 <optee_directory>/tee-pageable_v2.bin \
|
||||
--tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \
|
||||
--tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \
|
||||
--nt-fw <u-boot_directory>/u-boot-nodtb.bin \
|
||||
--nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \
|
||||
--nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \
|
||||
--hw-config <u-boot_directory>/u-boot.dtb \
|
||||
--fw-config build/stm32mp1/debug/fdts/fw-config.dtb \
|
||||
--stm32mp-cfg-cert build/stm32mp1/cert_images/stm32mp_cfg_cert.crt
|
||||
|
||||
tools/fiptool/fiptool create --tos-fw <optee_directory>/tee-header_v2.bin \
|
||||
--tos-fw-extra1 <optee_directory>/tee-pager_v2.bin \
|
||||
--tos-fw-extra2 <optee_directory>/tee-pageable_v2.bin \
|
||||
--nt-fw <u-boot_directory>/u-boot-nodtb.bin \
|
||||
--hw-config <u-boot_directory>/u-boot.dtb \
|
||||
--fw-config build/stm32mp1/debug/fdts/fw-config.dtb \
|
||||
--tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \
|
||||
--tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \
|
||||
--nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \
|
||||
--nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \
|
||||
--stm32mp-cfg-cert build/stm32mp1/cert_images/stm32mp_cfg_cert.crt stm32mp1.fip
|
||||
|
||||
|
||||
STM32IMAGE bootchain
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
} while (0)
|
||||
|
||||
#pragma weak plat_set_nv_ctr2
|
||||
#pragma weak plat_convert_pk
|
||||
|
||||
|
||||
static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a,
|
||||
|
@ -202,6 +203,10 @@ static int auth_signature(const auth_method_param_sig_t *param,
|
|||
NOTICE("ROTPK is not deployed on platform. "
|
||||
"Skipping ROTPK verification.\n");
|
||||
} else {
|
||||
/* platform may store the hash of a prefixed, suffixed or modified pk */
|
||||
rc = plat_convert_pk(pk_ptr, pk_len, &pk_ptr, &pk_len);
|
||||
return_if_error(rc);
|
||||
|
||||
/* Ask the crypto-module to verify the key hash */
|
||||
rc = crypto_mod_verify_hash(pk_ptr, pk_len,
|
||||
pk_hash_ptr, pk_hash_len);
|
||||
|
@ -301,6 +306,15 @@ int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused,
|
|||
return plat_set_nv_ctr(cookie, nv_ctr);
|
||||
}
|
||||
|
||||
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
|
||||
void **hashed_pk_ptr, unsigned int *hashed_pk_len)
|
||||
{
|
||||
*hashed_pk_ptr = full_pk_ptr;
|
||||
*hashed_pk_len = full_pk_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the parent id in the output parameter '*parent_id'
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -114,10 +114,10 @@ static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
|
|||
oid_len = mbedtls_oid_get_numeric_string(oid_str,
|
||||
MAX_OID_STR_LEN,
|
||||
&extn_oid);
|
||||
if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
|
||||
if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) {
|
||||
return IMG_PARSER_ERR;
|
||||
}
|
||||
if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
|
||||
if (((size_t)oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
|
||||
*ext = (void *)p;
|
||||
*ext_len = (unsigned int)len;
|
||||
return IMG_PARSER_OK;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
|
||||
* Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -8,10 +8,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/clk.h>
|
||||
|
@ -20,9 +16,17 @@
|
|||
#include <drivers/st/stm32mp_reset.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#if STM32_HASH_VER == 2
|
||||
#define DT_HASH_COMPAT "st,stm32f756-hash"
|
||||
#endif
|
||||
#if STM32_HASH_VER == 4
|
||||
#define DT_HASH_COMPAT "st,stm32mp13-hash"
|
||||
#endif
|
||||
|
||||
#define HASH_CR 0x00U
|
||||
#define HASH_DIN 0x04U
|
||||
|
@ -33,11 +37,22 @@
|
|||
/* Control Register */
|
||||
#define HASH_CR_INIT BIT(2)
|
||||
#define HASH_CR_DATATYPE_SHIFT U(4)
|
||||
|
||||
#if STM32_HASH_VER == 2
|
||||
#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))
|
||||
#endif
|
||||
#if STM32_HASH_VER == 4
|
||||
#define HASH_CR_ALGO_SHIFT U(17)
|
||||
#define HASH_CR_ALGO_SHA1 (0x0U << HASH_CR_ALGO_SHIFT)
|
||||
#define HASH_CR_ALGO_SHA224 (0x2U << HASH_CR_ALGO_SHIFT)
|
||||
#define HASH_CR_ALGO_SHA256 (0x3U << HASH_CR_ALGO_SHIFT)
|
||||
#define HASH_CR_ALGO_SHA384 (0xCU << HASH_CR_ALGO_SHIFT)
|
||||
#define HASH_CR_ALGO_SHA512_224 (0xDU << HASH_CR_ALGO_SHIFT)
|
||||
#define HASH_CR_ALGO_SHA512_256 (0xEU << HASH_CR_ALGO_SHIFT)
|
||||
#define HASH_CR_ALGO_SHA512 (0xFU << HASH_CR_ALGO_SHIFT)
|
||||
#endif
|
||||
|
||||
/* Status Flags */
|
||||
#define HASH_SR_DCIS BIT(1)
|
||||
|
@ -51,6 +66,10 @@
|
|||
#define SHA1_DIGEST_SIZE 20U
|
||||
#define SHA224_DIGEST_SIZE 28U
|
||||
#define SHA256_DIGEST_SIZE 32U
|
||||
#define SHA384_DIGEST_SIZE 48U
|
||||
#define SHA512_224_DIGEST_SIZE 28U
|
||||
#define SHA512_256_DIGEST_SIZE 32U
|
||||
#define SHA512_DIGEST_SIZE 64U
|
||||
|
||||
#define RESET_TIMEOUT_US_1MS 1000U
|
||||
#define HASH_TIMEOUT_US 10000U
|
||||
|
@ -131,10 +150,12 @@ static void hash_hw_init(enum stm32_hash_algo_mode mode)
|
|||
reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT);
|
||||
|
||||
switch (mode) {
|
||||
#if STM32_HASH_VER == 2
|
||||
case HASH_MD5SUM:
|
||||
reg |= HASH_CR_ALGO_MD5;
|
||||
stm32_hash.digest_size = MD5_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
case HASH_SHA1:
|
||||
reg |= HASH_CR_ALGO_SHA1;
|
||||
stm32_hash.digest_size = SHA1_DIGEST_SIZE;
|
||||
|
@ -143,6 +164,16 @@ static void hash_hw_init(enum stm32_hash_algo_mode mode)
|
|||
reg |= HASH_CR_ALGO_SHA224;
|
||||
stm32_hash.digest_size = SHA224_DIGEST_SIZE;
|
||||
break;
|
||||
#if STM32_HASH_VER == 4
|
||||
case HASH_SHA384:
|
||||
reg |= HASH_CR_ALGO_SHA384;
|
||||
stm32_hash.digest_size = SHA384_DIGEST_SIZE;
|
||||
break;
|
||||
case HASH_SHA512:
|
||||
reg |= HASH_CR_ALGO_SHA512;
|
||||
stm32_hash.digest_size = SHA512_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
/* Default selected algo is SHA256 */
|
||||
case HASH_SHA256:
|
||||
default:
|
||||
|
@ -171,13 +202,12 @@ static int hash_get_digest(uint8_t *digest)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -298,17 +328,9 @@ int stm32_hash_register(void)
|
|||
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
|
||||
/* BL32 uses hash if it is assigned only to secure world */
|
||||
if (hash_info.status == DT_SECURE) {
|
||||
stm32mp_register_secure_periph_iomem(hash_info.base);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (node == -FDT_ERR_NOTFOUND) {
|
||||
|
|
707
drivers/st/crypto/stm32_pka.c
Normal file
707
drivers/st/crypto/stm32_pka.c
Normal file
|
@ -0,0 +1,707 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <drivers/clk.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/st/stm32_pka.h>
|
||||
#include <drivers/st/stm32mp_reset.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* For our comprehension in this file
|
||||
* _len are in BITs
|
||||
* _size are in BYTEs
|
||||
* _nbw are in number of PKA_word (PKA_word = u64)
|
||||
*/
|
||||
|
||||
#define UINT8_LEN 8U
|
||||
#define UINT64_LEN (UINT8_LEN * sizeof(uint64_t))
|
||||
#define WORD_SIZE (sizeof(uint64_t))
|
||||
#define OP_NBW_FROM_LEN(len) (DIV_ROUND_UP_2EVAL((len), UINT64_LEN) + 1)
|
||||
#define OP_NBW_FROM_SIZE(s) OP_NBW_FROM_LEN((s) * UINT8_LEN)
|
||||
#define OP_SIZE_FROM_SIZE(s) (OP_NBW_FROM_SIZE(s) * WORD_SIZE)
|
||||
|
||||
#define DT_PKA_COMPAT "st,stm32-pka64"
|
||||
|
||||
#define MAX_ECC_SIZE_LEN 640U
|
||||
#define MAX_EO_NBW OP_NBW_FROM_LEN(MAX_ECC_SIZE_LEN)
|
||||
|
||||
/* PKA registers */
|
||||
/* PKA control register */
|
||||
#define _PKA_CR 0x0U
|
||||
/* PKA status register */
|
||||
#define _PKA_SR 0x4U
|
||||
/* PKA clear flag register */
|
||||
#define _PKA_CLRFR 0x8U
|
||||
/* PKA version register */
|
||||
#define _PKA_VERR 0x1FF4U
|
||||
/* PKA identification register */
|
||||
#define _PKA_IPIDR 0x1FF8U
|
||||
|
||||
/* PKA control register fields */
|
||||
#define _PKA_CR_MODE_MASK GENMASK(13, 8)
|
||||
#define _PKA_CR_MODE_SHIFT 8U
|
||||
#define _PKA_CR_MODE_ADD 0x9U
|
||||
#define _PKA_CR_MODE_ECDSA_VERIF 0x26U
|
||||
#define _PKA_CR_START BIT(1)
|
||||
#define _PKA_CR_EN BIT(0)
|
||||
|
||||
/* PKA status register fields */
|
||||
#define _PKA_SR_BUSY BIT(16)
|
||||
#define _PKA_SR_LMF BIT(1)
|
||||
#define _PKA_SR_INITOK BIT(0)
|
||||
|
||||
/* PKA it flag fields (used in CR, SR and CLRFR) */
|
||||
#define _PKA_IT_MASK (GENMASK(21, 19) | BIT(17))
|
||||
#define _PKA_IT_SHIFT 17U
|
||||
#define _PKA_IT_OPERR BIT(21)
|
||||
#define _PKA_IT_ADDRERR BIT(20)
|
||||
#define _PKA_IT_RAMERR BIT(19)
|
||||
#define _PKA_IT_PROCEND BIT(17)
|
||||
|
||||
/* PKA version register fields */
|
||||
#define _PKA_VERR_MAJREV_MASK GENMASK(7, 4)
|
||||
#define _PKA_VERR_MAJREV_SHIFT 4U
|
||||
#define _PKA_VERR_MINREV_MASK GENMASK(3, 0)
|
||||
#define _PKA_VERR_MINREV_SHIFT 0U
|
||||
|
||||
/* RAM magic offset */
|
||||
#define _PKA_RAM_START 0x400U
|
||||
#define _PKA_RAM_SIZE 5336U
|
||||
|
||||
/* ECDSA verification */
|
||||
#define _PKA_RAM_N_LEN 0x408U /* 64 */
|
||||
#define _PKA_RAM_P_LEN 0x4C8U /* 64 */
|
||||
#define _PKA_RAM_A_SIGN 0x468U /* 64 */
|
||||
#define _PKA_RAM_A 0x470U /* EOS */
|
||||
#define _PKA_RAM_P 0x4D0U /* EOS */
|
||||
#define _PKA_RAM_XG 0x678U /* EOS */
|
||||
#define _PKA_RAM_YG 0x6D0U /* EOS */
|
||||
#define _PKA_RAM_XQ 0x12F8U /* EOS */
|
||||
#define _PKA_RAM_YQ 0x1350U /* EOS */
|
||||
#define _PKA_RAM_SIGN_R 0x10E0U /* EOS */
|
||||
#define _PKA_RAM_SIGN_S 0xC68U /* EOS */
|
||||
#define _PKA_RAM_HASH_Z 0x13A8U /* EOS */
|
||||
#define _PKA_RAM_PRIME_N 0x1088U /* EOS */
|
||||
#define _PKA_RAM_ECDSA_VERIFY 0x5D0U /* 64 */
|
||||
#define _PKA_RAM_ECDSA_VERIFY_VALID 0xD60DULL
|
||||
#define _PKA_RAM_ECDSA_VERIFY_INVALID 0xA3B7ULL
|
||||
|
||||
#define PKA_TIMEOUT_US 1000000U
|
||||
#define TIMEOUT_US_1MS 1000U
|
||||
#define PKA_RESET_DELAY 20U
|
||||
|
||||
struct curve_parameters {
|
||||
uint32_t a_sign; /* 0 positive, 1 negative */
|
||||
uint8_t *a; /* Curve coefficient |a| */
|
||||
size_t a_size;
|
||||
uint8_t *p; /* Curve modulus value */
|
||||
uint32_t p_len;
|
||||
uint8_t *xg; /* Curve base point G coordinate x */
|
||||
size_t xg_size;
|
||||
uint8_t *yg; /* Curve base point G coordinate y */
|
||||
size_t yg_size;
|
||||
uint8_t *n; /* Curve prime order n */
|
||||
uint32_t n_len;
|
||||
};
|
||||
|
||||
static const struct curve_parameters curve_def[] = {
|
||||
#if PKA_USE_NIST_P256
|
||||
[PKA_NIST_P256] = {
|
||||
.p_len = 256U,
|
||||
.n_len = 256U,
|
||||
.p = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
.n = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
|
||||
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51},
|
||||
.a_sign = 1U,
|
||||
.a = (uint8_t[]){0x03},
|
||||
.a_size = 1U,
|
||||
.xg = (uint8_t[]){0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47,
|
||||
0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2,
|
||||
0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
|
||||
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96},
|
||||
.xg_size = 32U,
|
||||
.yg = (uint8_t[]){0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B,
|
||||
0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16,
|
||||
0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
|
||||
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5},
|
||||
.yg_size = 32U,
|
||||
},
|
||||
#endif
|
||||
#if PKA_USE_BRAINPOOL_P256R1
|
||||
[PKA_BRAINPOOL_P256R1] = {
|
||||
.p_len = 256,
|
||||
.n_len = 256,
|
||||
.p = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
|
||||
0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
|
||||
0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
|
||||
0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77},
|
||||
.n = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
|
||||
0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
|
||||
0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
|
||||
0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7},
|
||||
.a = (uint8_t[]){0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57,
|
||||
0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7,
|
||||
0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C,
|
||||
0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9},
|
||||
.a_size = 32U,
|
||||
.xg = (uint8_t[]){0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB,
|
||||
0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF,
|
||||
0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2,
|
||||
0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62},
|
||||
.xg_size = 32U,
|
||||
.yg = (uint8_t[]){0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD,
|
||||
0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9,
|
||||
0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54,
|
||||
0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97},
|
||||
.yg_size = 32U,
|
||||
},
|
||||
#endif
|
||||
#if PKA_USE_BRAINPOOL_P256T1
|
||||
[PKA_BRAINPOOL_P256T1] = {
|
||||
.p_len = 256,
|
||||
.n_len = 256,
|
||||
.p = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
|
||||
0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
|
||||
0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
|
||||
0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77},
|
||||
.n = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
|
||||
0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
|
||||
0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
|
||||
0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7},
|
||||
.a = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
|
||||
0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
|
||||
0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
|
||||
0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74},
|
||||
.a_size = 32U,
|
||||
.xg = (uint8_t[]){0xA3, 0xE8, 0xEB, 0x3C, 0xC1, 0xCF, 0xE7, 0xB7,
|
||||
0x73, 0x22, 0x13, 0xB2, 0x3A, 0x65, 0x61, 0x49,
|
||||
0xAF, 0xA1, 0x42, 0xC4, 0x7A, 0xAF, 0xBC, 0x2B,
|
||||
0x79, 0xA1, 0x91, 0x56, 0x2E, 0x13, 0x05, 0xF4},
|
||||
.xg_size = 32U,
|
||||
.yg = (uint8_t[]){0x2D, 0x99, 0x6C, 0x82, 0x34, 0x39, 0xC5, 0x6D,
|
||||
0x7F, 0x7B, 0x22, 0xE1, 0x46, 0x44, 0x41, 0x7E,
|
||||
0x69, 0xBC, 0xB6, 0xDE, 0x39, 0xD0, 0x27, 0x00,
|
||||
0x1D, 0xAB, 0xE8, 0xF3, 0x5B, 0x25, 0xC9, 0xBE},
|
||||
.yg_size = 32U,
|
||||
},
|
||||
#endif
|
||||
#if PKA_USE_NIST_P521
|
||||
[PKA_NIST_P521] = {
|
||||
.p_len = 521,
|
||||
.n_len = 521,
|
||||
.p = (uint8_t[]){ 0x01, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
.n = (uint8_t[]){ 0x01, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
|
||||
0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b,
|
||||
0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0,
|
||||
0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
|
||||
0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09},
|
||||
.a_sign = 1,
|
||||
.a = (uint8_t[]){0x03},
|
||||
.a_size = 1U,
|
||||
.xg = (uint8_t[]){ 0xc6,
|
||||
0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd,
|
||||
0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42,
|
||||
0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21,
|
||||
0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba,
|
||||
0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28,
|
||||
0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde,
|
||||
0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b,
|
||||
0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66},
|
||||
.xg_size = 65U,
|
||||
.yg = (uint8_t[]){ 0x01, 0x18,
|
||||
0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04,
|
||||
0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
|
||||
0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68,
|
||||
0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c,
|
||||
0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
|
||||
0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61,
|
||||
0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40,
|
||||
0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50},
|
||||
.yg_size = 66U,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct stm32_pka_platdata pka_pdata;
|
||||
|
||||
#pragma weak stm32_pka_get_platdata
|
||||
|
||||
int stm32_pka_get_platdata(struct stm32_pka_platdata *pdata)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int stm32_pka_parse_fdt(void)
|
||||
{
|
||||
int node;
|
||||
struct dt_node_info info;
|
||||
void *fdt;
|
||||
|
||||
if (fdt_get_address(&fdt) == 0) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
node = dt_get_node(&info, -1, DT_PKA_COMPAT);
|
||||
if (node < 0) {
|
||||
ERROR("No PKA entry in DT\n");
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
if (info.status == DT_DISABLED) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
if ((info.base == 0) || (info.clock < 0) || (info.reset < 0)) {
|
||||
return -FDT_ERR_BADVALUE;
|
||||
}
|
||||
|
||||
pka_pdata.base = (uintptr_t)info.base;
|
||||
pka_pdata.clock_id = (unsigned long)info.clock;
|
||||
pka_pdata.reset_id = (unsigned int)info.reset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pka_wait_bit(uintptr_t base, uint32_t bit)
|
||||
{
|
||||
uint64_t timeout = timeout_init_us(PKA_TIMEOUT_US);
|
||||
|
||||
while ((mmio_read_32(base + _PKA_SR) & bit) != bit) {
|
||||
if (timeout_elapsed(timeout)) {
|
||||
WARN("timeout waiting %x\n", bit);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void pka_disable(uintptr_t base)
|
||||
{
|
||||
mmio_clrbits_32(base + _PKA_CR, _PKA_CR_EN);
|
||||
}
|
||||
|
||||
static int pka_enable(uintptr_t base, uint32_t mode)
|
||||
{
|
||||
/* Set mode and disable interrupts */
|
||||
mmio_clrsetbits_32(base + _PKA_CR, _PKA_IT_MASK | _PKA_CR_MODE_MASK,
|
||||
_PKA_CR_MODE_MASK & (mode << _PKA_CR_MODE_SHIFT));
|
||||
|
||||
mmio_setbits_32(base + _PKA_CR, _PKA_CR_EN);
|
||||
|
||||
return pka_wait_bit(base, _PKA_SR_INITOK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Data are already loaded in PKA internal RAM
|
||||
* MODE is set
|
||||
* We start process, and wait for its end.
|
||||
*/
|
||||
static int stm32_pka_process(uintptr_t base)
|
||||
{
|
||||
mmio_setbits_32(base + _PKA_CR, _PKA_CR_START);
|
||||
|
||||
return pka_wait_bit(base, _PKA_IT_PROCEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write ECC operand to PKA RAM.
|
||||
* @note PKA expect to write u64 word, each u64 are: the least significant bit is
|
||||
* bit 0; the most significant bit is bit 63.
|
||||
* We write eo_nbw (ECC operand Size) u64, value that depends of the chosen
|
||||
* prime modulus length in bits.
|
||||
* First less signicant u64 is written to low address
|
||||
* Most significant u64 to higher address.
|
||||
* And at last address we write a u64(0x0)
|
||||
* @note This function doesn't only manage endianness (as bswap64 do), but also
|
||||
* complete most significant incomplete u64 with 0 (if data is not a u64
|
||||
* multiple), and fill u64 last address with 0.
|
||||
* @param addr: PKA_RAM address to write the buffer 'data'
|
||||
* @param data: is a BYTE list with most significant bytes first
|
||||
* @param data_size: nb of byte in data
|
||||
* @param eo_nbw: is ECC Operand size in 64bits word (including the extra 0)
|
||||
* (note it depends of the prime modulus length, not the data size)
|
||||
* @retval 0 if OK.
|
||||
* -EINVAL if data_size and eo_nbw are inconsistent, ie data doesn't
|
||||
* fit in defined eo_nbw, or eo_nbw bigger than hardware limit.
|
||||
*/
|
||||
static int write_eo_data(uintptr_t addr, uint8_t *data, unsigned int data_size,
|
||||
unsigned int eo_nbw)
|
||||
{
|
||||
uint32_t word_index;
|
||||
int data_index;
|
||||
|
||||
if ((eo_nbw < OP_NBW_FROM_SIZE(data_size)) || (eo_nbw > MAX_EO_NBW)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Fill value */
|
||||
data_index = (int)data_size - 1;
|
||||
for (word_index = 0U; word_index < eo_nbw; word_index++) {
|
||||
uint64_t tmp = 0ULL;
|
||||
unsigned int i = 0U; /* index in the tmp U64 word */
|
||||
|
||||
/* Stop if end of tmp or end of data */
|
||||
while ((i < sizeof(tmp)) && (data_index >= 0)) {
|
||||
tmp |= (uint64_t)(data[data_index]) << (UINT8_LEN * i);
|
||||
i++; /* Move byte index in current (u64)tmp */
|
||||
data_index--; /* Move to just next most significat byte */
|
||||
}
|
||||
|
||||
mmio_write_64(addr + word_index * sizeof(tmp), tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int get_ecc_op_nbword(enum stm32_pka_ecdsa_curve_id cid)
|
||||
{
|
||||
if (cid >= ARRAY_SIZE(curve_def)) {
|
||||
ERROR("CID %u is out of boundaries\n", cid);
|
||||
panic();
|
||||
}
|
||||
|
||||
return OP_NBW_FROM_LEN(curve_def[cid].n_len);
|
||||
}
|
||||
|
||||
static int stm32_pka_ecdsa_verif_configure_curve(uintptr_t base, enum stm32_pka_ecdsa_curve_id cid)
|
||||
{
|
||||
int ret;
|
||||
unsigned int eo_nbw = get_ecc_op_nbword(cid);
|
||||
|
||||
mmio_write_64(base + _PKA_RAM_N_LEN, curve_def[cid].n_len);
|
||||
mmio_write_64(base + _PKA_RAM_P_LEN, curve_def[cid].p_len);
|
||||
mmio_write_64(base + _PKA_RAM_A_SIGN, curve_def[cid].a_sign);
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_A, curve_def[cid].a, curve_def[cid].a_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_PRIME_N,
|
||||
curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN),
|
||||
eo_nbw);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_P, curve_def[cid].p,
|
||||
div_round_up(curve_def[cid].p_len, UINT8_LEN), eo_nbw);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_XG, curve_def[cid].xg, curve_def[cid].xg_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_YG, curve_def[cid].yg, curve_def[cid].yg_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_pka_ecdsa_verif_check_return(uintptr_t base)
|
||||
{
|
||||
uint64_t value;
|
||||
uint32_t sr;
|
||||
|
||||
sr = mmio_read_32(base + _PKA_SR);
|
||||
if ((sr & (_PKA_IT_OPERR | _PKA_IT_ADDRERR | _PKA_IT_RAMERR)) != 0) {
|
||||
WARN("Detected error(s): %s%s%s\n",
|
||||
(sr & _PKA_IT_OPERR) ? "Operation " : "",
|
||||
(sr & _PKA_IT_ADDRERR) ? "Address " : "",
|
||||
(sr & _PKA_IT_RAMERR) ? "RAM" : "");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value = mmio_read_64(base + _PKA_RAM_ECDSA_VERIFY);
|
||||
if (value == _PKA_RAM_ECDSA_VERIFY_VALID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (value == _PKA_RAM_ECDSA_VERIFY_INVALID) {
|
||||
return -EAUTH;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if BigInt stored in data is 0
|
||||
*
|
||||
* @param data: a BYTE array with most significant bytes first
|
||||
* @param size: data size
|
||||
*
|
||||
* @retval: true: if data represents a 0 value (ie all bytes == 0)
|
||||
* false: if data represents a non-zero value.
|
||||
*/
|
||||
static bool is_zero(uint8_t *data, unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0U; i < size; i++) {
|
||||
if (data[i] != 0U) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two BigInt:
|
||||
* @param xdata_a: a BYTE array with most significant bytes first
|
||||
* @param size_a: nb of Byte of 'a'
|
||||
* @param data_b: a BYTE array with most significant bytes first
|
||||
* @param size_b: nb of Byte of 'b'
|
||||
*
|
||||
* @retval: true if data_a < data_b
|
||||
* false if data_a >= data_b
|
||||
*/
|
||||
static bool is_smaller(uint8_t *data_a, unsigned int size_a,
|
||||
uint8_t *data_b, unsigned int size_b)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i = MAX(size_a, size_b) + 1U;
|
||||
do {
|
||||
uint8_t a, b;
|
||||
|
||||
i--;
|
||||
if (size_a < i) {
|
||||
a = 0U;
|
||||
} else {
|
||||
a = data_a[size_a - i];
|
||||
}
|
||||
|
||||
if (size_b < i) {
|
||||
b = 0U;
|
||||
} else {
|
||||
b = data_b[size_b - i];
|
||||
}
|
||||
|
||||
if (a < b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a > b) {
|
||||
return false;
|
||||
}
|
||||
} while (i != 0U);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int stm32_pka_ecdsa_check_param(void *sig_r_ptr, unsigned int sig_r_size,
|
||||
void *sig_s_ptr, unsigned int sig_s_size,
|
||||
void *pk_x_ptr, unsigned int pk_x_size,
|
||||
void *pk_y_ptr, unsigned int pk_y_size,
|
||||
enum stm32_pka_ecdsa_curve_id cid)
|
||||
{
|
||||
/* Public Key check */
|
||||
/* Check Xq < p */
|
||||
if (!is_smaller(pk_x_ptr, pk_x_size,
|
||||
curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
|
||||
WARN("%s Xq < p inval\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check Yq < p */
|
||||
if (!is_smaller(pk_y_ptr, pk_y_size,
|
||||
curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
|
||||
WARN("%s Yq < p inval\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Signature check */
|
||||
/* Check 0 < r < n */
|
||||
if (!is_smaller(sig_r_ptr, sig_r_size,
|
||||
curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
|
||||
!is_zero(sig_r_ptr, sig_r_size)) {
|
||||
WARN("%s 0< r < n inval\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check 0 < s < n */
|
||||
if (!is_smaller(sig_s_ptr, sig_s_size,
|
||||
curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
|
||||
!is_zero(sig_s_ptr, sig_s_size)) {
|
||||
WARN("%s 0< s < n inval\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Initialize the PKA driver.
|
||||
* @param None.
|
||||
* @retval 0 if OK, negative value else.
|
||||
*/
|
||||
int stm32_pka_init(void)
|
||||
{
|
||||
int err;
|
||||
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
||||
uint32_t ver;
|
||||
uint32_t id;
|
||||
#endif
|
||||
|
||||
err = stm32_pka_parse_fdt();
|
||||
if (err != 0) {
|
||||
err = stm32_pka_get_platdata(&pka_pdata);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
clk_enable(pka_pdata.clock_id);
|
||||
|
||||
if (stm32mp_reset_assert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
udelay(PKA_RESET_DELAY);
|
||||
if (stm32mp_reset_deassert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
||||
id = mmio_read_32(pka_pdata.base + _PKA_IPIDR);
|
||||
ver = mmio_read_32(pka_pdata.base + _PKA_VERR);
|
||||
|
||||
VERBOSE("STM32 PKA[%x] V%u.%u\n", id,
|
||||
(ver & _PKA_VERR_MAJREV_MASK) >> _PKA_VERR_MAJREV_SHIFT,
|
||||
(ver & _PKA_VERR_MINREV_MASK) >> _PKA_VERR_MINREV_SHIFT);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size,
|
||||
void *sig_r_ptr, unsigned int sig_r_size,
|
||||
void *sig_s_ptr, unsigned int sig_s_size,
|
||||
void *pk_x_ptr, unsigned int pk_x_size,
|
||||
void *pk_y_ptr, unsigned int pk_y_size,
|
||||
enum stm32_pka_ecdsa_curve_id cid)
|
||||
{
|
||||
int ret;
|
||||
uintptr_t base = pka_pdata.base;
|
||||
unsigned int eo_nbw = get_ecc_op_nbword(cid);
|
||||
|
||||
if ((hash == NULL) || (sig_r_ptr == NULL) || (sig_s_ptr == NULL) ||
|
||||
(pk_x_ptr == NULL) || (pk_y_ptr == NULL)) {
|
||||
INFO("%s invalid input param\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = stm32_pka_ecdsa_check_param(sig_r_ptr, sig_r_size,
|
||||
sig_s_ptr, sig_s_size,
|
||||
pk_x_ptr, pk_x_size,
|
||||
pk_y_ptr, pk_y_size,
|
||||
cid);
|
||||
if (ret < 0) {
|
||||
INFO("%s check param error %d\n", __func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((mmio_read_32(base + _PKA_SR) & _PKA_SR_BUSY) == _PKA_SR_BUSY) {
|
||||
INFO("%s busy\n", __func__);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Fill PKA RAM */
|
||||
/* With curve id values */
|
||||
ret = stm32_pka_ecdsa_verif_configure_curve(base, cid);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* With pubkey */
|
||||
ret = write_eo_data(base + _PKA_RAM_XQ, pk_x_ptr, pk_x_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_YQ, pk_y_ptr, pk_y_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* With hash */
|
||||
ret = write_eo_data(base + _PKA_RAM_HASH_Z, hash, hash_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* With signature */
|
||||
ret = write_eo_data(base + _PKA_RAM_SIGN_R, sig_r_ptr, sig_r_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = write_eo_data(base + _PKA_RAM_SIGN_S, sig_s_ptr, sig_s_size, eo_nbw);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set mode to ecdsa signature verification */
|
||||
ret = pka_enable(base, _PKA_CR_MODE_ECDSA_VERIF);
|
||||
if (ret < 0) {
|
||||
WARN("%s set mode pka error %d\n", __func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Start processing and wait end */
|
||||
ret = stm32_pka_process(base);
|
||||
if (ret < 0) {
|
||||
WARN("%s process error %d\n", __func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check return status */
|
||||
ret = stm32_pka_ecdsa_verif_check_return(base);
|
||||
|
||||
/* Unset end proc */
|
||||
mmio_setbits_32(base + _PKA_CLRFR, _PKA_IT_PROCEND);
|
||||
|
||||
out:
|
||||
/* Disable PKA (will stop all pending proccess and reset RAM) */
|
||||
pka_disable(base);
|
||||
|
||||
return ret;
|
||||
}
|
269
drivers/st/crypto/stm32_rng.c
Normal file
269
drivers/st/crypto/stm32_rng.c
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <drivers/clk.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/st/stm32_rng.h>
|
||||
#include <drivers/st/stm32mp_reset.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#if STM32_RNG_VER == 2
|
||||
#define DT_RNG_COMPAT "st,stm32-rng"
|
||||
#endif
|
||||
#if STM32_RNG_VER == 4
|
||||
#define DT_RNG_COMPAT "st,stm32mp13-rng"
|
||||
#endif
|
||||
#define RNG_CR 0x00U
|
||||
#define RNG_SR 0x04U
|
||||
#define RNG_DR 0x08U
|
||||
|
||||
#define RNG_CR_RNGEN BIT(2)
|
||||
#define RNG_CR_IE BIT(3)
|
||||
#define RNG_CR_CED BIT(5)
|
||||
#define RNG_CR_CLKDIV GENMASK(19, 16)
|
||||
#define RNG_CR_CLKDIV_SHIFT 16U
|
||||
#define RNG_CR_CONDRST BIT(30)
|
||||
|
||||
#define RNG_SR_DRDY BIT(0)
|
||||
#define RNG_SR_CECS BIT(1)
|
||||
#define RNG_SR_SECS BIT(2)
|
||||
#define RNG_SR_CEIS BIT(5)
|
||||
#define RNG_SR_SEIS BIT(6)
|
||||
|
||||
#define RNG_TIMEOUT_US 100000U
|
||||
#define RNG_TIMEOUT_STEP_US 10U
|
||||
|
||||
#define TIMEOUT_US_1MS 1000U
|
||||
|
||||
#define RNG_NIST_CONFIG_A 0x00F40F00U
|
||||
#define RNG_NIST_CONFIG_B 0x01801000U
|
||||
#define RNG_NIST_CONFIG_C 0x00F00D00U
|
||||
#define RNG_NIST_CONFIG_MASK GENMASK(25, 8)
|
||||
|
||||
#define RNG_MAX_NOISE_CLK_FREQ 48000000U
|
||||
|
||||
struct stm32_rng_instance {
|
||||
uintptr_t base;
|
||||
unsigned long clock;
|
||||
};
|
||||
|
||||
static struct stm32_rng_instance stm32_rng;
|
||||
|
||||
static void seed_error_recovery(void)
|
||||
{
|
||||
uint8_t i __maybe_unused;
|
||||
|
||||
/* Recommended by the SoC reference manual */
|
||||
mmio_clrbits_32(stm32_rng.base + RNG_SR, RNG_SR_SEIS);
|
||||
dmbsy();
|
||||
|
||||
#if STM32_RNG_VER == 2
|
||||
/* No Auto-reset on version 2, need to clean FIFO */
|
||||
for (i = 12U; i != 0U; i--) {
|
||||
(void)mmio_read_32(stm32_rng.base + RNG_DR);
|
||||
}
|
||||
|
||||
dmbsy();
|
||||
#endif
|
||||
|
||||
if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_SEIS) != 0U) {
|
||||
ERROR("RNG noise\n");
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t stm32_rng_clock_freq_restrain(void)
|
||||
{
|
||||
unsigned long clock_rate;
|
||||
uint32_t clock_div = 0U;
|
||||
|
||||
clock_rate = clk_get_rate(stm32_rng.clock);
|
||||
|
||||
/*
|
||||
* Get the exponent to apply on the CLKDIV field in RNG_CR register
|
||||
* No need to handle the case when clock-div > 0xF as it is physically
|
||||
* impossible
|
||||
*/
|
||||
while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) {
|
||||
clock_div++;
|
||||
}
|
||||
|
||||
VERBOSE("RNG clk rate : %lu\n", clk_get_rate(stm32_rng.clock) >> clock_div);
|
||||
|
||||
return clock_div;
|
||||
}
|
||||
|
||||
static int stm32_rng_enable(void)
|
||||
{
|
||||
uint32_t sr;
|
||||
uint64_t timeout;
|
||||
uint32_t clock_div __maybe_unused;
|
||||
|
||||
#if STM32_RNG_VER == 2
|
||||
mmio_write_32(stm32_rng.base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED);
|
||||
#endif
|
||||
#if STM32_RNG_VER == 4
|
||||
/* Reset internal block and disable CED bit */
|
||||
clock_div = stm32_rng_clock_freq_restrain();
|
||||
|
||||
/* Update configuration fields */
|
||||
mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_NIST_CONFIG_MASK,
|
||||
RNG_NIST_CONFIG_A | RNG_CR_CONDRST | RNG_CR_CED);
|
||||
|
||||
mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CLKDIV,
|
||||
(clock_div << RNG_CR_CLKDIV_SHIFT));
|
||||
|
||||
mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
|
||||
#endif
|
||||
timeout = timeout_init_us(RNG_TIMEOUT_US);
|
||||
sr = mmio_read_32(stm32_rng.base + RNG_SR);
|
||||
while ((sr & RNG_SR_DRDY) == 0U) {
|
||||
if (timeout_elapsed(timeout)) {
|
||||
WARN("Timeout waiting\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if ((sr & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
|
||||
seed_error_recovery();
|
||||
timeout = timeout_init_us(RNG_TIMEOUT_US);
|
||||
}
|
||||
|
||||
udelay(RNG_TIMEOUT_STEP_US);
|
||||
sr = mmio_read_32(stm32_rng.base + RNG_SR);
|
||||
}
|
||||
|
||||
VERBOSE("Init RNG done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* stm32_rng_read - Read a number of random bytes from RNG
|
||||
* out: pointer to the output buffer
|
||||
* size: number of bytes to be read
|
||||
* Return 0 on success, non-0 on failure
|
||||
*/
|
||||
int stm32_rng_read(uint8_t *out, uint32_t size)
|
||||
{
|
||||
uint8_t *buf = out;
|
||||
size_t len = size;
|
||||
int nb_tries;
|
||||
uint32_t data32;
|
||||
int rc = 0;
|
||||
unsigned int count;
|
||||
|
||||
if (stm32_rng.base == 0U) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
while (len != 0U) {
|
||||
nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US;
|
||||
do {
|
||||
uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR);
|
||||
|
||||
if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
|
||||
seed_error_recovery();
|
||||
}
|
||||
|
||||
udelay(RNG_TIMEOUT_STEP_US);
|
||||
nb_tries--;
|
||||
if (nb_tries == 0) {
|
||||
rc = -ETIMEDOUT;
|
||||
goto bail;
|
||||
}
|
||||
} while ((mmio_read_32(stm32_rng.base + RNG_SR) &
|
||||
RNG_SR_DRDY) == 0U);
|
||||
|
||||
count = 4U;
|
||||
while (len != 0U) {
|
||||
data32 = mmio_read_32(stm32_rng.base + RNG_DR);
|
||||
count--;
|
||||
|
||||
memcpy(buf, &data32, MIN(len, sizeof(uint32_t)));
|
||||
buf += MIN(len, sizeof(uint32_t));
|
||||
len -= MIN(len, sizeof(uint32_t));
|
||||
|
||||
if (count == 0U) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bail:
|
||||
if (rc != 0) {
|
||||
memset(out, 0, buf - out);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* stm32_rng_init: Initialize rng from DT
|
||||
* return 0 on success, negative value on failure
|
||||
*/
|
||||
int stm32_rng_init(void)
|
||||
{
|
||||
void *fdt;
|
||||
struct dt_node_info dt_rng;
|
||||
int node;
|
||||
|
||||
if (stm32_rng.base != 0U) {
|
||||
/* Driver is already initialized */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fdt_get_address(&fdt) == 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
node = dt_get_node(&dt_rng, -1, DT_RNG_COMPAT);
|
||||
if (node < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dt_rng.status == DT_DISABLED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(dt_rng.base != 0U);
|
||||
|
||||
stm32_rng.base = dt_rng.base;
|
||||
|
||||
if (dt_rng.clock < 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
stm32_rng.clock = (unsigned long)dt_rng.clock;
|
||||
clk_enable(stm32_rng.clock);
|
||||
|
||||
if (dt_rng.reset >= 0) {
|
||||
int ret;
|
||||
|
||||
ret = stm32mp_reset_assert((unsigned long)dt_rng.reset,
|
||||
TIMEOUT_US_1MS);
|
||||
if (ret != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
udelay(20);
|
||||
|
||||
ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset,
|
||||
TIMEOUT_US_1MS);
|
||||
if (ret != 0) {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
return stm32_rng_enable();
|
||||
}
|
913
drivers/st/crypto/stm32_saes.c
Normal file
913
drivers/st/crypto/stm32_saes.c
Normal file
|
@ -0,0 +1,913 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <drivers/clk.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/st/stm32_saes.h>
|
||||
#include <drivers/st/stm32mp_reset.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define UINT8_BIT 8U
|
||||
#define AES_BLOCK_SIZE_BIT 128U
|
||||
#define AES_BLOCK_SIZE (AES_BLOCK_SIZE_BIT / UINT8_BIT)
|
||||
|
||||
#define AES_KEYSIZE_128 16U
|
||||
#define AES_KEYSIZE_256 32U
|
||||
#define AES_IVSIZE 16U
|
||||
|
||||
/* SAES control register */
|
||||
#define _SAES_CR 0x0U
|
||||
/* SAES status register */
|
||||
#define _SAES_SR 0x04U
|
||||
/* SAES data input register */
|
||||
#define _SAES_DINR 0x08U
|
||||
/* SAES data output register */
|
||||
#define _SAES_DOUTR 0x0CU
|
||||
/* SAES key registers [0-3] */
|
||||
#define _SAES_KEYR0 0x10U
|
||||
#define _SAES_KEYR1 0x14U
|
||||
#define _SAES_KEYR2 0x18U
|
||||
#define _SAES_KEYR3 0x1CU
|
||||
/* SAES initialization vector registers [0-3] */
|
||||
#define _SAES_IVR0 0x20U
|
||||
#define _SAES_IVR1 0x24U
|
||||
#define _SAES_IVR2 0x28U
|
||||
#define _SAES_IVR3 0x2CU
|
||||
/* SAES key registers [4-7] */
|
||||
#define _SAES_KEYR4 0x30U
|
||||
#define _SAES_KEYR5 0x34U
|
||||
#define _SAES_KEYR6 0x38U
|
||||
#define _SAES_KEYR7 0x3CU
|
||||
/* SAES suspend registers [0-7] */
|
||||
#define _SAES_SUSPR0 0x40U
|
||||
#define _SAES_SUSPR1 0x44U
|
||||
#define _SAES_SUSPR2 0x48U
|
||||
#define _SAES_SUSPR3 0x4CU
|
||||
#define _SAES_SUSPR4 0x50U
|
||||
#define _SAES_SUSPR5 0x54U
|
||||
#define _SAES_SUSPR6 0x58U
|
||||
#define _SAES_SUSPR7 0x5CU
|
||||
/* SAES Interrupt Enable Register */
|
||||
#define _SAES_IER 0x300U
|
||||
/* SAES Interrupt Status Register */
|
||||
#define _SAES_ISR 0x304U
|
||||
/* SAES Interrupt Clear Register */
|
||||
#define _SAES_ICR 0x308U
|
||||
|
||||
/* SAES control register fields */
|
||||
#define _SAES_CR_RESET_VALUE 0x0U
|
||||
#define _SAES_CR_IPRST BIT(31)
|
||||
#define _SAES_CR_KEYSEL_MASK GENMASK(30, 28)
|
||||
#define _SAES_CR_KEYSEL_SHIFT 28U
|
||||
#define _SAES_CR_KEYSEL_SOFT 0x0U
|
||||
#define _SAES_CR_KEYSEL_DHUK 0x1U
|
||||
#define _SAES_CR_KEYSEL_BHK 0x2U
|
||||
#define _SAES_CR_KEYSEL_BHU_XOR_BH_K 0x4U
|
||||
#define _SAES_CR_KEYSEL_TEST 0x7U
|
||||
#define _SAES_CR_KSHAREID_MASK GENMASK(27, 26)
|
||||
#define _SAES_CR_KSHAREID_SHIFT 26U
|
||||
#define _SAES_CR_KSHAREID_CRYP 0x0U
|
||||
#define _SAES_CR_KEYMOD_MASK GENMASK(25, 24)
|
||||
#define _SAES_CR_KEYMOD_SHIFT 24U
|
||||
#define _SAES_CR_KEYMOD_NORMAL 0x0U
|
||||
#define _SAES_CR_KEYMOD_WRAPPED 0x1U
|
||||
#define _SAES_CR_KEYMOD_SHARED 0x2U
|
||||
#define _SAES_CR_NPBLB_MASK GENMASK(23, 20)
|
||||
#define _SAES_CR_NPBLB_SHIFT 20U
|
||||
#define _SAES_CR_KEYPROT BIT(19)
|
||||
#define _SAES_CR_KEYSIZE BIT(18)
|
||||
#define _SAES_CR_GCMPH_MASK GENMASK(14, 13)
|
||||
#define _SAES_CR_GCMPH_SHIFT 13U
|
||||
#define _SAES_CR_GCMPH_INIT 0U
|
||||
#define _SAES_CR_GCMPH_HEADER 1U
|
||||
#define _SAES_CR_GCMPH_PAYLOAD 2U
|
||||
#define _SAES_CR_GCMPH_FINAL 3U
|
||||
#define _SAES_CR_DMAOUTEN BIT(12)
|
||||
#define _SAES_CR_DMAINEN BIT(11)
|
||||
#define _SAES_CR_CHMOD_MASK (BIT(16) | GENMASK(6, 5))
|
||||
#define _SAES_CR_CHMOD_SHIFT 5U
|
||||
#define _SAES_CR_CHMOD_ECB 0x0U
|
||||
#define _SAES_CR_CHMOD_CBC 0x1U
|
||||
#define _SAES_CR_CHMOD_CTR 0x2U
|
||||
#define _SAES_CR_CHMOD_GCM 0x3U
|
||||
#define _SAES_CR_CHMOD_GMAC 0x3U
|
||||
#define _SAES_CR_CHMOD_CCM 0x800U
|
||||
#define _SAES_CR_MODE_MASK GENMASK(4, 3)
|
||||
#define _SAES_CR_MODE_SHIFT 3U
|
||||
#define _SAES_CR_MODE_ENC 0U
|
||||
#define _SAES_CR_MODE_KEYPREP 1U
|
||||
#define _SAES_CR_MODE_DEC 2U
|
||||
#define _SAES_CR_DATATYPE_MASK GENMASK(2, 1)
|
||||
#define _SAES_CR_DATATYPE_SHIFT 1U
|
||||
#define _SAES_CR_DATATYPE_NONE 0U
|
||||
#define _SAES_CR_DATATYPE_HALF_WORD 1U
|
||||
#define _SAES_CR_DATATYPE_BYTE 2U
|
||||
#define _SAES_CR_DATATYPE_BIT 3U
|
||||
#define _SAES_CR_EN BIT(0)
|
||||
|
||||
/* SAES status register fields */
|
||||
#define _SAES_SR_KEYVALID BIT(7)
|
||||
#define _SAES_SR_BUSY BIT(3)
|
||||
#define _SAES_SR_WRERR BIT(2)
|
||||
#define _SAES_SR_RDERR BIT(1)
|
||||
#define _SAES_SR_CCF BIT(0)
|
||||
|
||||
/* SAES interrupt registers fields */
|
||||
#define _SAES_I_RNG_ERR BIT(3)
|
||||
#define _SAES_I_KEY_ERR BIT(2)
|
||||
#define _SAES_I_RW_ERR BIT(1)
|
||||
#define _SAES_I_CC BIT(0)
|
||||
|
||||
#define SAES_TIMEOUT_US 100000U
|
||||
#define TIMEOUT_US_1MS 1000U
|
||||
#define SAES_RESET_DELAY 20U
|
||||
|
||||
#define IS_CHAINING_MODE(mod, cr) \
|
||||
(((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT))
|
||||
|
||||
#define SET_CHAINING_MODE(mod, cr) \
|
||||
mmio_clrsetbits_32((cr), _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT)
|
||||
|
||||
#define pragma weak stm32_saes_get_platdata
|
||||
|
||||
static struct stm32_saes_platdata saes_pdata;
|
||||
|
||||
int stm32_saes_get_platdata(struct stm32_saes_platdata *pdata)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata)
|
||||
{
|
||||
int node;
|
||||
struct dt_node_info info;
|
||||
void *fdt;
|
||||
|
||||
if (fdt_get_address(&fdt) == 0) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
node = dt_get_node(&info, -1, DT_SAES_COMPAT);
|
||||
if (node < 0) {
|
||||
ERROR("No SAES entry in DT\n");
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
if (info.status == DT_DISABLED) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
if ((info.base == 0U) || (info.clock < 0) || (info.reset < 0)) {
|
||||
return -FDT_ERR_BADVALUE;
|
||||
}
|
||||
|
||||
pdata->base = (uintptr_t)info.base;
|
||||
pdata->clock_id = (unsigned long)info.clock;
|
||||
pdata->reset_id = (unsigned int)info.reset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool does_chaining_mode_need_iv(uint32_t cr)
|
||||
{
|
||||
return !(IS_CHAINING_MODE(ECB, cr));
|
||||
}
|
||||
|
||||
static bool is_encrypt(uint32_t cr)
|
||||
{
|
||||
return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
|
||||
}
|
||||
|
||||
static bool is_decrypt(uint32_t cr)
|
||||
{
|
||||
return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
|
||||
}
|
||||
|
||||
static int wait_computation_completed(uintptr_t base)
|
||||
{
|
||||
uint64_t timeout = timeout_init_us(SAES_TIMEOUT_US);
|
||||
|
||||
while ((mmio_read_32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) {
|
||||
if (timeout_elapsed(timeout)) {
|
||||
WARN("%s: timeout\n", __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear_computation_completed(uintptr_t base)
|
||||
{
|
||||
mmio_setbits_32(base + _SAES_ICR, _SAES_I_CC);
|
||||
}
|
||||
|
||||
static int saes_start(struct stm32_saes_context *ctx)
|
||||
{
|
||||
uint64_t timeout;
|
||||
|
||||
/* Reset IP */
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
|
||||
udelay(SAES_RESET_DELAY);
|
||||
mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
|
||||
|
||||
timeout = timeout_init_us(SAES_TIMEOUT_US);
|
||||
while ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) == _SAES_SR_BUSY) {
|
||||
if (timeout_elapsed(timeout)) {
|
||||
WARN("%s: timeout\n", __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void saes_end(struct stm32_saes_context *ctx, int prev_error)
|
||||
{
|
||||
if (prev_error != 0) {
|
||||
/* Reset IP */
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
|
||||
udelay(SAES_RESET_DELAY);
|
||||
mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
|
||||
}
|
||||
|
||||
/* Disable the SAES peripheral */
|
||||
mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
}
|
||||
|
||||
static void saes_write_iv(struct stm32_saes_context *ctx)
|
||||
{
|
||||
/* If chaining mode need to restore IV */
|
||||
if (does_chaining_mode_need_iv(ctx->cr)) {
|
||||
uint8_t i;
|
||||
|
||||
/* Restore the _SAES_IVRx */
|
||||
for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
|
||||
mmio_write_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void saes_write_key(struct stm32_saes_context *ctx)
|
||||
{
|
||||
/* Restore the _SAES_KEYRx if SOFTWARE key */
|
||||
if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == (_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT)) {
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
|
||||
mmio_write_32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]);
|
||||
}
|
||||
|
||||
if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) {
|
||||
for (i = 0U; i < (AES_KEYSIZE_256 / 2U) / sizeof(uint32_t); i++) {
|
||||
mmio_write_32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t),
|
||||
ctx->key[i + 4U]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int saes_prepare_key(struct stm32_saes_context *ctx)
|
||||
{
|
||||
/* Disable the SAES peripheral */
|
||||
mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
|
||||
/* Set key size */
|
||||
if ((ctx->cr & _SAES_CR_KEYSIZE) != 0U) {
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
|
||||
} else {
|
||||
mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
|
||||
}
|
||||
|
||||
saes_write_key(ctx);
|
||||
|
||||
/* For ECB/CBC decryption, key preparation mode must be selected to populate the key */
|
||||
if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) &&
|
||||
is_decrypt(ctx->cr)) {
|
||||
int ret;
|
||||
|
||||
/* Select Mode 2 */
|
||||
mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
|
||||
_SAES_CR_MODE_KEYPREP << _SAES_CR_MODE_SHIFT);
|
||||
|
||||
/* Enable SAES */
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
|
||||
/* Wait Computation completed */
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
/* Set Mode 3 */
|
||||
mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
|
||||
_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int save_context(struct stm32_saes_context *ctx)
|
||||
{
|
||||
if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_CCF) != 0U) {
|
||||
/* Device should not be in a processing phase */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Save CR */
|
||||
ctx->cr = mmio_read_32(ctx->base + _SAES_CR);
|
||||
|
||||
/* If chaining mode need to save current IV */
|
||||
if (does_chaining_mode_need_iv(ctx->cr)) {
|
||||
uint8_t i;
|
||||
|
||||
/* Save IV */
|
||||
for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
|
||||
ctx->iv[i] = mmio_read_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SAES peripheral */
|
||||
mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To resume the processing of a message */
|
||||
static int restore_context(struct stm32_saes_context *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* IP should be disabled */
|
||||
if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) {
|
||||
VERBOSE("%s: Device is still enabled\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Reset internal state */
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
|
||||
|
||||
/* Restore the _SAES_CR */
|
||||
mmio_write_32(ctx->base + _SAES_CR, ctx->cr);
|
||||
|
||||
/* Preparation decrypt key */
|
||||
ret = saes_prepare_key(ctx);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
saes_write_iv(ctx);
|
||||
|
||||
/* Enable the SAES peripheral */
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize SAES driver.
|
||||
* @param None.
|
||||
* @retval 0 if OK; negative value else.
|
||||
*/
|
||||
int stm32_saes_driver_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = stm32_saes_parse_fdt(&saes_pdata);
|
||||
if (err != 0) {
|
||||
err = stm32_saes_get_platdata(&saes_pdata);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
clk_enable(saes_pdata.clock_id);
|
||||
if (stm32mp_reset_assert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
udelay(SAES_RESET_DELAY);
|
||||
if (stm32mp_reset_deassert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a AES computation.
|
||||
* @param ctx: SAES process context
|
||||
* @param is_dec: true if decryption, false if encryption
|
||||
* @param ch_mode: define the chaining mode
|
||||
* @param key_select: define where the key comes from.
|
||||
* @param key: pointer to key (if key_select is KEY_SOFT, else unused)
|
||||
* @param key_size: key size
|
||||
* @param iv: pointer to initialization vectore (unsed if ch_mode is ECB)
|
||||
* @param iv_size: iv size
|
||||
* @note this function doesn't access to hardware but store in ctx the values
|
||||
*
|
||||
* @retval 0 if OK; negative value else.
|
||||
*/
|
||||
int stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
|
||||
enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select,
|
||||
const void *key, size_t key_size, const void *iv, size_t iv_size)
|
||||
{
|
||||
unsigned int i;
|
||||
const uint32_t *iv_u32;
|
||||
const uint32_t *key_u32;
|
||||
|
||||
ctx->assoc_len = 0U;
|
||||
ctx->load_len = 0U;
|
||||
|
||||
ctx->base = saes_pdata.base;
|
||||
ctx->cr = _SAES_CR_RESET_VALUE;
|
||||
|
||||
/* We want buffer to be u32 aligned */
|
||||
assert((uintptr_t)key % __alignof__(uint32_t) == 0);
|
||||
assert((uintptr_t)iv % __alignof__(uint32_t) == 0);
|
||||
|
||||
iv_u32 = iv;
|
||||
key_u32 = key;
|
||||
|
||||
if (is_dec) {
|
||||
/* Save Mode 3 = decrypt */
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
|
||||
_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
|
||||
} else {
|
||||
/* Save Mode 1 = crypt */
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
|
||||
_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
|
||||
}
|
||||
|
||||
/* Save chaining mode */
|
||||
switch (ch_mode) {
|
||||
case STM32_SAES_MODE_ECB:
|
||||
SET_CHAINING_MODE(ECB, (uintptr_t)&(ctx->cr));
|
||||
break;
|
||||
case STM32_SAES_MODE_CBC:
|
||||
SET_CHAINING_MODE(CBC, (uintptr_t)&(ctx->cr));
|
||||
break;
|
||||
case STM32_SAES_MODE_CTR:
|
||||
SET_CHAINING_MODE(CTR, (uintptr_t)&(ctx->cr));
|
||||
break;
|
||||
case STM32_SAES_MODE_GCM:
|
||||
SET_CHAINING_MODE(GCM, (uintptr_t)&(ctx->cr));
|
||||
break;
|
||||
case STM32_SAES_MODE_CCM:
|
||||
SET_CHAINING_MODE(CCM, (uintptr_t)&(ctx->cr));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data.
|
||||
* so we won't need to
|
||||
* htobe32(data) before write to DINR
|
||||
* nor
|
||||
* be32toh after reading from DOUTR
|
||||
*
|
||||
* But note that wrap key only accept _SAES_CR_DATATYPE_NONE
|
||||
*/
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK,
|
||||
_SAES_CR_DATATYPE_BYTE << _SAES_CR_DATATYPE_SHIFT);
|
||||
|
||||
/* Configure keysize */
|
||||
switch (key_size) {
|
||||
case AES_KEYSIZE_128:
|
||||
mmio_clrbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
|
||||
break;
|
||||
case AES_KEYSIZE_256:
|
||||
mmio_setbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Configure key */
|
||||
switch (key_select) {
|
||||
case STM32_SAES_KEY_SOFT:
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
|
||||
_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
|
||||
/* Save key */
|
||||
switch (key_size) {
|
||||
case AES_KEYSIZE_128:
|
||||
/* First 16 bytes == 4 u32 */
|
||||
for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
|
||||
mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[3 - i]));
|
||||
/* /!\ we save the key in HW byte order
|
||||
* and word order : key[i] is for _SAES_KEYRi
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case AES_KEYSIZE_256:
|
||||
for (i = 0U; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) {
|
||||
mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[7 - i]));
|
||||
/* /!\ we save the key in HW byte order
|
||||
* and word order : key[i] is for _SAES_KEYRi
|
||||
*/
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case STM32_SAES_KEY_DHU:
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
|
||||
_SAES_CR_KEYSEL_DHUK << _SAES_CR_KEYSEL_SHIFT);
|
||||
break;
|
||||
case STM32_SAES_KEY_BH:
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
|
||||
_SAES_CR_KEYSEL_BHK << _SAES_CR_KEYSEL_SHIFT);
|
||||
break;
|
||||
case STM32_SAES_KEY_BHU_XOR_BH:
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
|
||||
_SAES_CR_KEYSEL_BHU_XOR_BH_K << _SAES_CR_KEYSEL_SHIFT);
|
||||
break;
|
||||
case STM32_SAES_KEY_WRAPPED:
|
||||
mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
|
||||
_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Save IV */
|
||||
if (ch_mode != STM32_SAES_MODE_ECB) {
|
||||
if ((iv == NULL) || (iv_size != AES_IVSIZE)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
|
||||
mmio_write_32((uintptr_t)(ctx->iv + i), htobe32(iv_u32[3 - i]));
|
||||
/* /!\ We save the iv in HW byte order */
|
||||
}
|
||||
}
|
||||
|
||||
return saes_start(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update (or start) a AES authentificate process of associated data (CCM or GCM).
|
||||
* @param ctx: SAES process context
|
||||
* @param last_block: true if last assoc data block
|
||||
* @param data: pointer to associated data
|
||||
* @param data_size: data size
|
||||
*
|
||||
* @retval 0 if OK; negative value else.
|
||||
*/
|
||||
int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block,
|
||||
uint8_t *data, size_t data_size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t *data_u32;
|
||||
unsigned int i = 0U;
|
||||
|
||||
/* We want buffers to be u32 aligned */
|
||||
assert((uintptr_t)data % __alignof__(uint32_t) == 0);
|
||||
data_u32 = (uint32_t *)data;
|
||||
|
||||
/* Init phase */
|
||||
ret = restore_context(ctx);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
if ((data == NULL) || (data_size == 0U)) {
|
||||
/* No associated data */
|
||||
/* ret already = 0 */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* There is an header/associated data phase */
|
||||
mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
|
||||
_SAES_CR_GCMPH_HEADER << _SAES_CR_GCMPH_SHIFT);
|
||||
|
||||
/* Enable the SAES peripheral */
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
|
||||
while (i < round_down(data_size, AES_BLOCK_SIZE)) {
|
||||
unsigned int w; /* Word index */
|
||||
|
||||
w = i / sizeof(uint32_t);
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 0U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 1U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 2U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 3U]);
|
||||
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
/* Process next block */
|
||||
i += AES_BLOCK_SIZE;
|
||||
ctx->assoc_len += AES_BLOCK_SIZE_BIT;
|
||||
}
|
||||
|
||||
/* Manage last block if not a block size multiple */
|
||||
if ((last_block) && (i < data_size)) {
|
||||
/* We don't manage unaligned last block yet */
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret != 0) {
|
||||
saes_end(ctx, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update (or start) a AES authenticate and de/encrypt with payload data (CCM or GCM).
|
||||
* @param ctx: SAES process context
|
||||
* @param last_block: true if last payload data block
|
||||
* @param data_in: pointer to payload
|
||||
* @param data_out: pointer where to save de/encrypted payload
|
||||
* @param data_size: payload size
|
||||
*
|
||||
* @retval 0 if OK; negative value else.
|
||||
*/
|
||||
int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block,
|
||||
uint8_t *data_in, uint8_t *data_out, size_t data_size)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t *data_in_u32;
|
||||
uint32_t *data_out_u32;
|
||||
unsigned int i = 0U;
|
||||
uint32_t prev_cr;
|
||||
|
||||
/* We want buffers to be u32 aligned */
|
||||
assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
|
||||
assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
|
||||
data_in_u32 = (uint32_t *)data_in;
|
||||
data_out_u32 = (uint32_t *)data_out;
|
||||
|
||||
prev_cr = mmio_read_32(ctx->base + _SAES_CR);
|
||||
|
||||
if ((data_in == NULL) || (data_size == 0U)) {
|
||||
/* there is no data */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* There is a load phase */
|
||||
mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
|
||||
_SAES_CR_GCMPH_PAYLOAD << _SAES_CR_GCMPH_SHIFT);
|
||||
|
||||
if ((prev_cr & _SAES_CR_GCMPH_MASK) ==
|
||||
(_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
|
||||
/* Still in initialization phase, no header
|
||||
* We need to enable the SAES peripheral
|
||||
*/
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
}
|
||||
|
||||
while (i < round_down(data_size, AES_BLOCK_SIZE)) {
|
||||
unsigned int w; /* Word index */
|
||||
|
||||
w = i / sizeof(uint32_t);
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
|
||||
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
/* Process next block */
|
||||
i += AES_BLOCK_SIZE;
|
||||
ctx->load_len += AES_BLOCK_SIZE_BIT;
|
||||
}
|
||||
/* Manage last block if not a block size multiple */
|
||||
if ((last_block) && (i < data_size)) {
|
||||
uint32_t block_in[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
|
||||
uint32_t block_out[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
|
||||
|
||||
memcpy(block_in, data_in + i, data_size - i);
|
||||
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
mmio_write_32(ctx->base + _SAES_DINR, block_in[0U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, block_in[1U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, block_in[2U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, block_in[3U]);
|
||||
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s %d\n", __func__, __LINE__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
block_out[0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
block_out[1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
block_out[2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
block_out[3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
memcpy(data_out + i, block_out, data_size - i);
|
||||
|
||||
ctx->load_len += (data_size - i) * UINT8_BIT;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret != 0) {
|
||||
saes_end(ctx, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get authentication tag for AES authenticated algorithms (CCM or GCM).
|
||||
* @param ctx: SAES process context
|
||||
* @param tag: pointer where to save the tag
|
||||
* @param data_size: tag size
|
||||
*
|
||||
* @retval 0 if OK; negative value else.
|
||||
*/
|
||||
int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag,
|
||||
size_t tag_size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t tag_u32[4];
|
||||
uint32_t prev_cr;
|
||||
|
||||
prev_cr = mmio_read_32(ctx->base + _SAES_CR);
|
||||
|
||||
mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
|
||||
_SAES_CR_GCMPH_FINAL << _SAES_CR_GCMPH_SHIFT);
|
||||
|
||||
if ((prev_cr & _SAES_CR_GCMPH_MASK) == (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
|
||||
/* Still in initialization phase, no header
|
||||
* We need to enable the SAES peripheral
|
||||
*/
|
||||
mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
|
||||
}
|
||||
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
mmio_write_32(ctx->base + _SAES_DINR, 0);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, ctx->assoc_len);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, 0);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, ctx->load_len);
|
||||
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
tag_u32[0] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
tag_u32[1] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
tag_u32[2] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
tag_u32[3] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size));
|
||||
|
||||
out:
|
||||
saes_end(ctx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update (or start) a AES de/encrypt process (ECB, CBC or CTR).
|
||||
* @param ctx: SAES process context
|
||||
* @param last_block: true if last payload data block
|
||||
* @param data_in: pointer to payload
|
||||
* @param data_out: pointer where to save de/encrypted payload
|
||||
* @param data_size: payload size
|
||||
*
|
||||
* @retval 0 if OK; negative value else.
|
||||
*/
|
||||
int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block,
|
||||
uint8_t *data_in, uint8_t *data_out, size_t data_size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t *data_in_u32;
|
||||
uint32_t *data_out_u32;
|
||||
unsigned int i = 0U;
|
||||
|
||||
/* We want buffers to be u32 aligned */
|
||||
assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
|
||||
assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
|
||||
data_in_u32 = (uint32_t *)data_in;
|
||||
data_out_u32 = (uint32_t *)data_out;
|
||||
|
||||
if ((!last_block) &&
|
||||
(round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
|
||||
ERROR("%s: non last block must be multiple of 128 bits\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* In CBC encryption we need to manage specifically last 2 128bits
|
||||
* blocks if total size in not a block size aligned
|
||||
* work TODO. Currently return ENODEV.
|
||||
* Morevoer as we need to know last 2 block, if unaligned and
|
||||
* call with less than two block, return -EINVAL.
|
||||
*/
|
||||
if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) &&
|
||||
(round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
|
||||
if (data_size < AES_BLOCK_SIZE * 2U) {
|
||||
ERROR("if CBC, last part size should be at least 2 * AES_BLOCK_SIZE\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* Moreover the CBC specific padding for encrypt is not yet implemented */
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = restore_context(ctx);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (i < round_down(data_size, AES_BLOCK_SIZE)) {
|
||||
unsigned int w; /* Word index */
|
||||
|
||||
w = i / sizeof(uint32_t);
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
|
||||
mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
|
||||
|
||||
ret = wait_computation_completed(ctx->base);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No need to htobe() as we configure the HW to swap bytes */
|
||||
data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
|
||||
|
||||
clear_computation_completed(ctx->base);
|
||||
|
||||
/* Process next block */
|
||||
i += AES_BLOCK_SIZE;
|
||||
}
|
||||
/* Manage last block if not a block size multiple */
|
||||
|
||||
if ((last_block) && (i < data_size)) {
|
||||
/* In and out buffer have same size so should be AES_BLOCK_SIZE multiple */
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!last_block) {
|
||||
ret = save_context(ctx);
|
||||
}
|
||||
|
||||
out:
|
||||
/* If last block or error, end of SAES process */
|
||||
if (last_block || (ret != 0)) {
|
||||
saes_end(ctx, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -333,19 +333,6 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
|
|||
continue;
|
||||
}
|
||||
|
||||
result = stm32mp_check_header(header, buffer);
|
||||
if (result != 0) {
|
||||
ERROR("Header check failed\n");
|
||||
*length_read = 0;
|
||||
header->magic = 0;
|
||||
}
|
||||
|
||||
result = stm32mp_auth_image(header, buffer);
|
||||
if (result != 0) {
|
||||
ERROR("Authentication Failed (%i)\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz),
|
||||
CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz);
|
||||
|
||||
|
|
156
fdts/stm32mp1-cot-descriptors.dtsi
Normal file
156
fdts/stm32mp1-cot-descriptors.dtsi
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/nv_cntr_ids.h>
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <tools_share/tbbr_oid.h>
|
||||
|
||||
cot {
|
||||
manifests {
|
||||
compatible = "arm, cert-descs";
|
||||
|
||||
stm32mp_cfg_cert: stm32mp_cfg_cert {
|
||||
root-certificate;
|
||||
image-id = <STM32MP_CONFIG_CERT_ID>;
|
||||
antirollback-counter = <&trusted_nv_counter>;
|
||||
|
||||
hw_config_hash: hw_config_hash {
|
||||
oid = HW_CONFIG_HASH_OID;
|
||||
};
|
||||
|
||||
fw_config_hash: fw_config_hash {
|
||||
oid = FW_CONFIG_HASH_OID;
|
||||
};
|
||||
};
|
||||
|
||||
trusted_key_cert: trusted_key_cert {
|
||||
root-certificate;
|
||||
image-id = <TRUSTED_KEY_CERT_ID>;
|
||||
antirollback-counter = <&trusted_nv_counter>;
|
||||
|
||||
trusted_world_pk: trusted_world_pk {
|
||||
oid = TRUSTED_WORLD_PK_OID;
|
||||
};
|
||||
non_trusted_world_pk: non_trusted_world_pk {
|
||||
oid = NON_TRUSTED_WORLD_PK_OID;
|
||||
};
|
||||
};
|
||||
|
||||
trusted_os_fw_key_cert: trusted_os_fw_key_cert {
|
||||
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
|
||||
parent = <&trusted_key_cert>;
|
||||
signing-key = <&trusted_world_pk>;
|
||||
antirollback-counter = <&trusted_nv_counter>;
|
||||
|
||||
tos_fw_content_pk: tos_fw_content_pk {
|
||||
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
|
||||
};
|
||||
};
|
||||
|
||||
trusted_os_fw_content_cert: trusted_os_fw_content_cert {
|
||||
image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
|
||||
parent = <&trusted_os_fw_key_cert>;
|
||||
signing-key = <&tos_fw_content_pk>;
|
||||
antirollback-counter = <&trusted_nv_counter>;
|
||||
|
||||
tos_fw_hash: tos_fw_hash {
|
||||
oid = TRUSTED_OS_FW_HASH_OID;
|
||||
};
|
||||
tos_fw_extra1_hash: tos_fw_extra1_hash {
|
||||
oid = TRUSTED_OS_FW_EXTRA1_HASH_OID;
|
||||
};
|
||||
tos_fw_extra2_hash: tos_fw_extra2_hash {
|
||||
oid = TRUSTED_OS_FW_EXTRA2_HASH_OID;
|
||||
};
|
||||
tos_fw_config_hash: tos_fw_config_hash {
|
||||
oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
|
||||
};
|
||||
};
|
||||
|
||||
non_trusted_fw_key_cert: non_trusted_fw_key_cert {
|
||||
image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
|
||||
parent = <&trusted_key_cert>;
|
||||
signing-key = <&non_trusted_world_pk>;
|
||||
antirollback-counter = <&non_trusted_nv_counter>;
|
||||
|
||||
nt_fw_content_pk: nt_fw_content_pk {
|
||||
oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
|
||||
};
|
||||
};
|
||||
|
||||
non_trusted_fw_content_cert: non_trusted_fw_content_cert {
|
||||
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
|
||||
parent = <&non_trusted_fw_key_cert>;
|
||||
signing-key = <&nt_fw_content_pk>;
|
||||
antirollback-counter = <&non_trusted_nv_counter>;
|
||||
|
||||
nt_world_bl_hash: nt_world_bl_hash {
|
||||
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
images {
|
||||
compatible = "arm, img-descs";
|
||||
|
||||
hw_config {
|
||||
image-id = <HW_CONFIG_ID>;
|
||||
parent = <&stm32mp_cfg_cert>;
|
||||
hash = <&hw_config_hash>;
|
||||
};
|
||||
|
||||
fw_config {
|
||||
image-id = <FW_CONFIG_ID>;
|
||||
parent = <&stm32mp_cfg_cert>;
|
||||
hash = <&fw_config_hash>;
|
||||
};
|
||||
|
||||
bl32_image {
|
||||
image-id = <BL32_IMAGE_ID>;
|
||||
parent = <&trusted_os_fw_content_cert>;
|
||||
hash = <&tos_fw_hash>;
|
||||
};
|
||||
|
||||
bl32_extra1_image {
|
||||
image-id = <BL32_EXTRA1_IMAGE_ID>;
|
||||
parent = <&trusted_os_fw_content_cert>;
|
||||
hash = <&tos_fw_extra1_hash>;
|
||||
};
|
||||
|
||||
bl32_extra2_image {
|
||||
image-id = <BL32_EXTRA2_IMAGE_ID>;
|
||||
parent = <&trusted_os_fw_content_cert>;
|
||||
hash = <&tos_fw_extra2_hash>;
|
||||
};
|
||||
|
||||
tos_fw_config {
|
||||
image-id = <TOS_FW_CONFIG_ID>;
|
||||
parent = <&trusted_os_fw_content_cert>;
|
||||
hash = <&tos_fw_config_hash>;
|
||||
};
|
||||
|
||||
bl33_image {
|
||||
image-id = <BL33_IMAGE_ID>;
|
||||
parent = <&non_trusted_fw_content_cert>;
|
||||
hash = <&nt_world_bl_hash>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
non_volatile_counters: non_volatile_counters {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
trusted_nv_counter: trusted_nv_counter {
|
||||
id = <TRUSTED_NV_CTR_ID>;
|
||||
oid = TRUSTED_FW_NVCOUNTER_OID;
|
||||
};
|
||||
|
||||
non_trusted_nv_counter: non_trusted_nv_counter {
|
||||
id = <NON_TRUSTED_NV_CTR_ID>;
|
||||
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
|
||||
};
|
||||
};
|
|
@ -56,7 +56,30 @@
|
|||
bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
|
||||
hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
|
||||
tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
|
||||
nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
stm32mp_cfg_cert_uuid = "501d8dd2-8bce-49a5-84eb-559a9f2eaeaf";
|
||||
t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c";
|
||||
tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04";
|
||||
nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859";
|
||||
tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d";
|
||||
nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7";
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
tb_fw-config {
|
||||
compatible = "arm,tb_fw";
|
||||
|
||||
/* Disable authentication for development */
|
||||
disable_auth = <0x0>;
|
||||
|
||||
/* Use SRAM2 to manage the mbedTLS heap */
|
||||
mbedtls_heap_addr = <0x0 0x30004000>; /* SRAM2_BASE */
|
||||
mbedtls_heap_size = <0x2000>; /* SRAM2_SIZE */
|
||||
};
|
||||
|
||||
#include "stm32mp1-cot-descriptors.dtsi"
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
|
@ -455,6 +455,9 @@
|
|||
reg = <0xe4 0xc>;
|
||||
st,non-secure-otp;
|
||||
};
|
||||
enckey_otp: enckey_otp@170 {
|
||||
reg = <0x170 0x10>;
|
||||
};
|
||||
};
|
||||
/*
|
||||
* Break node order to solve dependency probe issue between
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
};
|
||||
|
||||
&pka {
|
||||
secure-status = "okay";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwr_regulators {
|
||||
|
@ -298,7 +298,7 @@
|
|||
};
|
||||
|
||||
&saes {
|
||||
secure-status = "okay";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc1 {
|
||||
|
|
|
@ -85,8 +85,33 @@
|
|||
bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
|
||||
hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
|
||||
tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
|
||||
nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
stm32mp_cfg_cert_uuid = "501d8dd2-8bce-49a5-84eb-559a9f2eaeaf";
|
||||
t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c";
|
||||
tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04";
|
||||
nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859";
|
||||
tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d";
|
||||
nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7";
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
tb_fw-config {
|
||||
compatible = "arm,tb_fw";
|
||||
|
||||
/* Disable authentication for development */
|
||||
disable_auth = <0x0>;
|
||||
|
||||
/*
|
||||
* The following two entries are placeholders for Mbed TLS
|
||||
* heap information.
|
||||
*/
|
||||
mbedtls_heap_addr = <0x0 0x0>;
|
||||
mbedtls_heap_size = <0x0>;
|
||||
};
|
||||
|
||||
#include "stm32mp1-cot-descriptors.dtsi"
|
||||
#endif
|
||||
#endif /* !STM32MP_USE_STM32IMAGE */
|
||||
};
|
||||
|
|
|
@ -487,6 +487,9 @@
|
|||
ts_cal2: calib@5e {
|
||||
reg = <0x5e 0x2>;
|
||||
};
|
||||
pkh_otp: pkh_otp@60 {
|
||||
reg = <0x60 0x20>;
|
||||
};
|
||||
mac_addr: mac_addr@e4 {
|
||||
reg = <0xe4 0x8>;
|
||||
st,non-secure-otp;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
|
||||
#endif
|
||||
#else /* Only using ECDSA keys. */
|
||||
#define PK_DER_LEN 91
|
||||
#define PK_DER_LEN 92
|
||||
#endif
|
||||
|
||||
#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019, STMicroelectronics - All Rights Reserved
|
||||
* Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -7,11 +7,19 @@
|
|||
#ifndef STM32_HASH_H
|
||||
#define STM32_HASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum stm32_hash_algo_mode {
|
||||
#if STM32_HASH_VER == 2
|
||||
HASH_MD5SUM,
|
||||
#endif
|
||||
HASH_SHA1,
|
||||
HASH_SHA224,
|
||||
HASH_SHA256
|
||||
HASH_SHA256,
|
||||
#if STM32_HASH_VER == 4
|
||||
HASH_SHA384,
|
||||
HASH_SHA512,
|
||||
#endif
|
||||
};
|
||||
|
||||
int stm32_hash_update(const uint8_t *buffer, size_t length);
|
||||
|
|
46
include/drivers/st/stm32_pka.h
Normal file
46
include/drivers/st/stm32_pka.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef STM32_PKA_H
|
||||
#define STM32_PKA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if !PKA_USE_NIST_P256 && !PKA_USE_BRAINPOOL_P256R1 && !PKA_USE_BRAINPOOL_P256T1 && \
|
||||
!PKA_USE_NIST_P521
|
||||
#error "At least one ECDSA curve needs to be selected"
|
||||
#endif
|
||||
|
||||
enum stm32_pka_ecdsa_curve_id {
|
||||
#if PKA_USE_NIST_P256
|
||||
PKA_NIST_P256,
|
||||
#endif
|
||||
#if PKA_USE_BRAINPOOL_P256R1
|
||||
PKA_BRAINPOOL_P256R1,
|
||||
#endif
|
||||
#if PKA_USE_BRAINPOOL_P256T1
|
||||
PKA_BRAINPOOL_P256T1,
|
||||
#endif
|
||||
#if PKA_USE_NIST_P521
|
||||
PKA_NIST_P521,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct stm32_pka_platdata {
|
||||
uintptr_t base;
|
||||
unsigned long clock_id;
|
||||
unsigned int reset_id;
|
||||
};
|
||||
|
||||
int stm32_pka_init(void);
|
||||
int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size,
|
||||
void *sig_r_ptr, unsigned int sig_r_size,
|
||||
void *sig_s_ptr, unsigned int sig_s_size,
|
||||
void *pk_x_ptr, unsigned int pk_x_size,
|
||||
void *pk_y_ptr, unsigned int pk_y_size,
|
||||
enum stm32_pka_ecdsa_curve_id cid);
|
||||
|
||||
#endif /* STM32_PKA_H */
|
15
include/drivers/st/stm32_rng.h
Normal file
15
include/drivers/st/stm32_rng.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef STM32_RNG_H
|
||||
#define STM32_RNG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int stm32_rng_read(uint8_t *out, uint32_t size);
|
||||
int stm32_rng_init(void);
|
||||
|
||||
#endif /* STM32_RNG_H */
|
59
include/drivers/st/stm32_saes.h
Normal file
59
include/drivers/st/stm32_saes.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef STM32_SAES_H
|
||||
#define STM32_SAES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define DT_SAES_COMPAT "st,stm32-saes"
|
||||
|
||||
struct stm32_saes_platdata {
|
||||
uintptr_t base;
|
||||
unsigned long clock_id;
|
||||
unsigned int reset_id;
|
||||
};
|
||||
|
||||
enum stm32_saes_chaining_mode {
|
||||
STM32_SAES_MODE_ECB,
|
||||
STM32_SAES_MODE_CBC,
|
||||
STM32_SAES_MODE_CTR,
|
||||
STM32_SAES_MODE_GCM,
|
||||
STM32_SAES_MODE_CCM, /* Not use in TF-A */
|
||||
};
|
||||
|
||||
enum stm32_saes_key_selection {
|
||||
STM32_SAES_KEY_SOFT,
|
||||
STM32_SAES_KEY_DHU, /* Derived HW unique key */
|
||||
STM32_SAES_KEY_BH, /* Boot HW key */
|
||||
STM32_SAES_KEY_BHU_XOR_BH, /* XOR of DHUK and BHK */
|
||||
STM32_SAES_KEY_WRAPPED
|
||||
};
|
||||
|
||||
struct stm32_saes_context {
|
||||
uintptr_t base;
|
||||
uint32_t cr;
|
||||
uint32_t assoc_len;
|
||||
uint32_t load_len;
|
||||
uint32_t key[8]; /* In HW byte order */
|
||||
uint32_t iv[4]; /* In HW byte order */
|
||||
};
|
||||
|
||||
int stm32_saes_driver_init(void);
|
||||
|
||||
int stm32_saes_init(struct stm32_saes_context *ctx, bool is_decrypt,
|
||||
enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select,
|
||||
const void *key, size_t key_len, const void *iv, size_t iv_len);
|
||||
int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block,
|
||||
uint8_t *data_in, uint8_t *data_out, size_t data_len);
|
||||
int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block,
|
||||
uint8_t *data, size_t data_len);
|
||||
int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block,
|
||||
uint8_t *data_in, uint8_t *data_out, size_t data_len);
|
||||
int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, size_t tag_len);
|
||||
#endif
|
|
@ -344,6 +344,8 @@ int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr);
|
|||
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
|
||||
int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc,
|
||||
unsigned int nv_ctr);
|
||||
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
|
||||
void **hashed_pk_ptr, unsigned int *hash_pk_len);
|
||||
int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size);
|
||||
int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
|
||||
size_t *key_len, unsigned int *flags,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -44,8 +44,8 @@ int fconf_populate_tbbr_dyn_config(uintptr_t config)
|
|||
/* Check if the value is boolean */
|
||||
if ((tbbr_dyn_config.disable_auth != 0U) &&
|
||||
(tbbr_dyn_config.disable_auth != 1U)) {
|
||||
WARN("Invalid value for `%s` cell %d\n",
|
||||
"disable_auth", tbbr_dyn_config.disable_auth);
|
||||
WARN("Invalid value for `%s` cell %u\n",
|
||||
"disable_auth", tbbr_dyn_config.disable_auth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ int fconf_populate_tbbr_dyn_config(uintptr_t config)
|
|||
}
|
||||
tbbr_dyn_config.mbedtls_heap_size = val32;
|
||||
|
||||
VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth",
|
||||
VERBOSE("%s%s%s %u\n", "FCONF: `tbbr.", "disable_auth",
|
||||
"` cell found with value =", tbbr_dyn_config.disable_auth);
|
||||
VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
|
||||
"` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <drivers/fwu/fwu_metadata.h>
|
||||
#include <drivers/io/io_block.h>
|
||||
#include <drivers/io/io_driver.h>
|
||||
#include <drivers/io/io_encrypted.h>
|
||||
#include <drivers/io/io_fip.h>
|
||||
#include <drivers/io/io_memmap.h>
|
||||
#include <drivers/io/io_mtd.h>
|
||||
|
@ -48,6 +49,11 @@ uintptr_t storage_dev_handle;
|
|||
|
||||
static const io_dev_connector_t *fip_dev_con;
|
||||
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
static const io_dev_connector_t *enc_dev_con;
|
||||
uintptr_t enc_dev_handle;
|
||||
#endif
|
||||
|
||||
#if STM32MP_SDMMC || STM32MP_EMMC
|
||||
static struct mmc_device_info mmc_info;
|
||||
|
||||
|
@ -118,6 +124,29 @@ int open_fip(const uintptr_t spec)
|
|||
return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
|
||||
}
|
||||
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
int open_enc_fip(const uintptr_t spec)
|
||||
{
|
||||
int result;
|
||||
uintptr_t local_image_handle;
|
||||
|
||||
result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = io_open(enc_dev_handle, spec, &local_image_handle);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
VERBOSE("Using encrypted FIP\n");
|
||||
io_close(local_image_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int open_storage(const uintptr_t spec)
|
||||
{
|
||||
return io_dev_init(storage_dev_handle, 0);
|
||||
|
@ -383,6 +412,15 @@ void stm32mp_io_setup(void)
|
|||
io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
|
||||
&fip_dev_handle);
|
||||
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
io_result = register_io_dev_enc(&enc_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
|
||||
&enc_dev_handle);
|
||||
assert(io_result == 0);
|
||||
#endif
|
||||
|
||||
switch (boot_context->boot_interface_selected) {
|
||||
#if STM32MP_SDMMC
|
||||
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef STM32MP_AUTH_H
|
||||
#define STM32MP_AUTH_H
|
||||
|
||||
struct stm32mp_auth_ops {
|
||||
uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out);
|
||||
uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
|
||||
uint8_t *signature, uint32_t ecc_algo);
|
||||
};
|
||||
|
||||
void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr);
|
||||
int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer);
|
||||
|
||||
#endif /* STM32MP_AUTH_H */
|
|
@ -109,16 +109,6 @@ void stm32mp_print_boardinfo(void);
|
|||
/* Initialise the IO layer and register platform IO devices */
|
||||
void stm32mp_io_setup(void);
|
||||
|
||||
#if STM32MP_USE_STM32IMAGE
|
||||
/*
|
||||
* Check that the STM32 header of a .stm32 binary image is valid
|
||||
* @param header: pointer to the stm32 image header
|
||||
* @param buffer: address of the binary image (payload)
|
||||
* @return: 0 on success, negative value in case of error
|
||||
*/
|
||||
int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer);
|
||||
#endif /* STM32MP_USE_STM32IMAGE */
|
||||
|
||||
/* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */
|
||||
int stm32mp_map_ddr_non_cacheable(void);
|
||||
int stm32mp_unmap_ddr(void);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, STMicroelectronics - All Rights Reserved
|
||||
* Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -13,11 +13,15 @@
|
|||
/* IO devices handle */
|
||||
extern uintptr_t storage_dev_handle;
|
||||
extern uintptr_t fip_dev_handle;
|
||||
extern uintptr_t enc_dev_handle;
|
||||
|
||||
extern io_block_spec_t image_block_spec;
|
||||
|
||||
/* Function declarations */
|
||||
int open_fip(const uintptr_t spec);
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
int open_enc_fip(const uintptr_t spec);
|
||||
#endif
|
||||
int open_storage(const uintptr_t spec);
|
||||
|
||||
#endif /* STM32MP_IO_STORAGE_H */
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <drivers/st/bsec.h>
|
||||
#include <drivers/st/stm32_hash.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
static const struct stm32mp_auth_ops *auth_ops;
|
||||
|
||||
void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr)
|
||||
{
|
||||
if ((init_ptr == NULL) ||
|
||||
(init_ptr->check_key == NULL) ||
|
||||
(init_ptr->verify_signature == NULL) ||
|
||||
(stm32_hash_register() != 0)) {
|
||||
panic();
|
||||
}
|
||||
|
||||
auth_ops = init_ptr;
|
||||
}
|
||||
|
||||
int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer)
|
||||
{
|
||||
int ret;
|
||||
uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
|
||||
uint32_t header_skip_cksum = sizeof(header->magic) +
|
||||
sizeof(header->image_signature) +
|
||||
sizeof(header->payload_checksum);
|
||||
|
||||
/* Check Security Status */
|
||||
if (!stm32mp_is_closed_device()) {
|
||||
if (header->option_flags != 0U) {
|
||||
WARN("Skip signature check (header option)\n");
|
||||
return 0;
|
||||
}
|
||||
INFO("Check signature on Open device\n");
|
||||
}
|
||||
|
||||
if (auth_ops == NULL) {
|
||||
ERROR("Device doesn't support image authentication\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
|
||||
STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check Public Key */
|
||||
if (auth_ops->check_key(header->ecc_pubk, NULL) != BOOT_API_RETURN_OK) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Compute end of header hash and payload hash */
|
||||
stm32_hash_init(HASH_SHA256);
|
||||
|
||||
ret = stm32_hash_update((uint8_t *)&header->header_version,
|
||||
sizeof(boot_api_image_header_t) -
|
||||
header_skip_cksum);
|
||||
if (ret != 0) {
|
||||
ERROR("Hash of header failed, %i\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = stm32_hash_final_update((uint8_t *)buffer,
|
||||
header->image_length, image_hash);
|
||||
if (ret != 0) {
|
||||
ERROR("Hash of payload failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Verify signature */
|
||||
if (auth_ops->verify_signature(image_hash, header->ecc_pubk,
|
||||
header->image_signature,
|
||||
header->ecc_algo_type) !=
|
||||
BOOT_API_RETURN_OK) {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
err:
|
||||
mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED);
|
||||
return ret;
|
||||
}
|
661
plat/st/common/stm32mp_crypto_lib.c
Normal file
661
plat/st/common/stm32mp_crypto_lib.c
Normal file
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/auth/crypto_mod.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <drivers/st/bsec.h>
|
||||
#include <drivers/st/stm32_hash.h>
|
||||
#include <drivers/st/stm32_pka.h>
|
||||
#include <drivers/st/stm32_rng.h>
|
||||
#include <drivers/st/stm32_saes.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <mbedtls/asn1.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/oid.h>
|
||||
#include <mbedtls/platform.h>
|
||||
#include <mbedtls/x509.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <tools_share/firmware_encrypted.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define CRYPTO_HASH_MAX_SIZE 32U
|
||||
#define CRYPTO_SIGN_MAX_SIZE 64U
|
||||
#define CRYPTO_PUBKEY_MAX_SIZE 64U
|
||||
#define CRYPTO_MAX_TAG_SIZE 16U
|
||||
|
||||
/* brainpoolP256t1 OID is not defined in mbedTLS */
|
||||
#define OID_EC_GRP_BP256T1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x08"
|
||||
|
||||
#if STM32MP_CRYPTO_ROM_LIB
|
||||
struct stm32mp_auth_ops {
|
||||
uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
|
||||
uint8_t *signature, uint32_t ecc_algo);
|
||||
};
|
||||
|
||||
static struct stm32mp_auth_ops auth_ops;
|
||||
#endif
|
||||
|
||||
static void crypto_lib_init(void)
|
||||
{
|
||||
boot_api_context_t *boot_context __maybe_unused;
|
||||
int ret;
|
||||
|
||||
NOTICE("TRUSTED_BOARD_BOOT support enabled\n");
|
||||
|
||||
ret = stm32_hash_register();
|
||||
if (ret != 0) {
|
||||
ERROR("HASH init (%d)\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
if (stm32mp_is_closed_device() || stm32mp_is_auth_supported()) {
|
||||
#if STM32MP_CRYPTO_ROM_LIB
|
||||
boot_context = (boot_api_context_t *)stm32mp_get_boot_ctx_address();
|
||||
auth_ops.verify_signature = boot_context->bootrom_ecdsa_verify_signature;
|
||||
#else
|
||||
/* Use hardware peripherals */
|
||||
if (stm32_rng_init() != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
if (stm32_saes_driver_init() != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
if (stm32_pka_init() != 0) {
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int get_plain_pk_from_asn1(void *pk_ptr, unsigned int pk_len, void **plain_pk,
|
||||
unsigned int *len, int *pk_alg)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_context mbedtls_pk = {0};
|
||||
unsigned char *p, *end;
|
||||
mbedtls_asn1_buf alg_params = {0};
|
||||
mbedtls_asn1_buf alg_oid = {0};
|
||||
|
||||
*plain_pk = NULL;
|
||||
*len = 0U;
|
||||
|
||||
/* Parse the public key */
|
||||
mbedtls_pk_init(&mbedtls_pk);
|
||||
p = (unsigned char *)pk_ptr;
|
||||
end = (unsigned char *)(p + pk_len);
|
||||
|
||||
ret = mbedtls_asn1_get_tag(&p, end, len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||
if (ret != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
end = p + *len;
|
||||
ret = mbedtls_asn1_get_alg(&p, end, &alg_oid, &alg_params);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pk_alg != NULL) {
|
||||
if ((strlen(MBEDTLS_OID_EC_GRP_SECP256R1) == alg_params.len) &&
|
||||
(memcmp(MBEDTLS_OID_EC_GRP_SECP256R1, alg_params.p, alg_params.len) == 0)) {
|
||||
*pk_alg = BOOT_API_ECDSA_ALGO_TYPE_P256NIST;
|
||||
} else if ((strlen(OID_EC_GRP_BP256T1) == alg_params.len) &&
|
||||
(memcmp(OID_EC_GRP_BP256T1, alg_params.p, alg_params.len) == 0)) {
|
||||
*pk_alg = BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256;
|
||||
} else {
|
||||
ERROR("%s: Algorithm is not supported\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mbedtls_asn1_get_bitstring_null(&p, end, len);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We remove the ident (0x04) first byte. */
|
||||
if ((*len < 1U) || (p[0] != MBEDTLS_ASN1_OCTET_STRING)) {
|
||||
VERBOSE("%s: not expected len or tag\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*len = *len - 1U;
|
||||
*plain_pk = p + 1U;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if STM32MP_CRYPTO_ROM_LIB
|
||||
uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
|
||||
uint8_t *signature, uint32_t ecc_algo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
|
||||
STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mmap_add_dynamic_region (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
ret = auth_ops.verify_signature(hash_in, pubkey_in, signature, ecc_algo);
|
||||
|
||||
if (ret != BOOT_API_RETURN_OK) {
|
||||
VERBOSE("%s: auth_ops.verify_sign (%d)\n", __func__, ret);
|
||||
ret = CRYPTO_ERR_SIGNATURE;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
|
||||
void **hashed_pk_ptr, unsigned int *hashed_pk_len)
|
||||
{
|
||||
return get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, hashed_pk_ptr, hashed_pk_len, NULL);
|
||||
}
|
||||
#else /* STM32MP_CRYPTO_ROM_LIB*/
|
||||
static uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
|
||||
uint8_t *signature, uint32_t ecc_algo)
|
||||
{
|
||||
int ret = -1;
|
||||
enum stm32_pka_ecdsa_curve_id cid;
|
||||
|
||||
switch (ecc_algo) {
|
||||
case BOOT_API_ECDSA_ALGO_TYPE_P256NIST:
|
||||
#if PKA_USE_NIST_P256
|
||||
cid = PKA_NIST_P256;
|
||||
ret = 0;
|
||||
#else
|
||||
WARN("%s nist_p256 requested but not included\n", __func__);
|
||||
#endif
|
||||
break;
|
||||
case BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256:
|
||||
#if PKA_USE_BRAINPOOL_P256T1
|
||||
cid = PKA_BRAINPOOL_P256T1;
|
||||
ret = 0;
|
||||
#else
|
||||
WARN("%s brainpool_p256t1 requested but not included\n", __func__);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
WARN("%s unexpected ecc_algo(%u)\n", __func__, ecc_algo);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
ret = stm32_pka_ecdsa_verif(hash_in,
|
||||
BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES,
|
||||
signature, BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
|
||||
signature + BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
|
||||
BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
|
||||
pubkey_in, BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
|
||||
pubkey_in + BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
|
||||
BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, cid);
|
||||
if (ret < 0) {
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
|
||||
void **hashed_pk_ptr, unsigned int *hashed_pk_len)
|
||||
{
|
||||
static uint8_t st_pk[CRYPTO_PUBKEY_MAX_SIZE + sizeof(uint32_t)];
|
||||
int ret;
|
||||
void *plain_pk;
|
||||
unsigned int len;
|
||||
int curve_id;
|
||||
uint32_t cid;
|
||||
|
||||
ret = get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, &plain_pk, &len, &curve_id);
|
||||
if ((ret != 0) || (len > CRYPTO_PUBKEY_MAX_SIZE)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cid = curve_id; /* we want value of curve_id (1 or 2) in a uint32_t */
|
||||
|
||||
memcpy(st_pk, &cid, sizeof(cid));
|
||||
memcpy(st_pk + sizeof(cid), plain_pk, len);
|
||||
|
||||
*hashed_pk_ptr = st_pk;
|
||||
*hashed_pk_len = len + sizeof(cid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* STM32MP_CRYPTO_ROM_LIB */
|
||||
|
||||
static int get_plain_digest_from_asn1(void *digest_ptr, unsigned int digest_len,
|
||||
uint8_t **out, size_t *out_len, mbedtls_md_type_t *md_alg)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_asn1_buf hash_oid, params;
|
||||
size_t len;
|
||||
unsigned char *p, *end;
|
||||
|
||||
*out = NULL;
|
||||
*out_len = 0U;
|
||||
|
||||
/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
|
||||
p = (unsigned char *)digest_ptr;
|
||||
end = p + digest_len;
|
||||
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
|
||||
MBEDTLS_ASN1_SEQUENCE);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the hash algorithm */
|
||||
ret = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mbedtls_oid_get_md_alg(&hash_oid, md_alg);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Length of hash must match the algorithm's size */
|
||||
if (len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = p;
|
||||
*out_len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_verify_signature(void *data_ptr, unsigned int data_len,
|
||||
void *sig_ptr, unsigned int sig_len,
|
||||
void *sig_alg, unsigned int sig_alg_len,
|
||||
void *pk_ptr, unsigned int pk_len)
|
||||
{
|
||||
uint8_t image_hash[CRYPTO_HASH_MAX_SIZE] = {0};
|
||||
uint8_t sig[CRYPTO_SIGN_MAX_SIZE];
|
||||
uint8_t my_pk[CRYPTO_PUBKEY_MAX_SIZE];
|
||||
int ret;
|
||||
size_t len;
|
||||
mbedtls_asn1_sequence seq;
|
||||
mbedtls_asn1_sequence *cur;
|
||||
unsigned char *p, *end;
|
||||
int curve_id;
|
||||
mbedtls_asn1_buf sig_oid, sig_params;
|
||||
mbedtls_md_type_t md_alg;
|
||||
mbedtls_pk_type_t pk_alg;
|
||||
size_t bignum_len = sizeof(sig) / 2U;
|
||||
unsigned int seq_num = 0U;
|
||||
|
||||
if (!stm32mp_is_closed_device() && !stm32mp_is_auth_supported()) {
|
||||
return CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get pointers to signature OID and parameters */
|
||||
p = (unsigned char *)sig_alg;
|
||||
end = (unsigned char *)(p + sig_alg_len);
|
||||
ret = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/* Get the actual signature algorithm (MD + PK) */
|
||||
ret = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mbedtls_oid_get_sig_alg (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
if ((md_alg != MBEDTLS_MD_SHA256) || (pk_alg != MBEDTLS_PK_ECDSA)) {
|
||||
VERBOSE("%s: md_alg=%u pk_alg=%u\n", __func__, md_alg, pk_alg);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
ret = get_plain_pk_from_asn1(pk_ptr, pk_len, &pk_ptr, &pk_len, &curve_id);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: get_plain_pk_from_asn1 (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/* We expect a known pk_len */
|
||||
if (pk_len != sizeof(my_pk)) {
|
||||
VERBOSE("%s: pk_len=%u sizeof(my_pk)=%zu)\n", __func__, pk_len, sizeof(my_pk));
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/* Need to copy as auth_ops.verify_signature
|
||||
* expects aligned public key.
|
||||
*/
|
||||
memcpy(my_pk, pk_ptr, sizeof(my_pk));
|
||||
|
||||
/* Get the signature (bitstring) */
|
||||
p = (unsigned char *)sig_ptr;
|
||||
end = (unsigned char *)(p + sig_len);
|
||||
ret = mbedtls_asn1_get_bitstring_null(&p, end, &len);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/* Get r and s from sequence */
|
||||
ret = mbedtls_asn1_get_sequence_of(&p, end, &seq, MBEDTLS_ASN1_INTEGER);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: mbedtls_asn1_get_sequence_of (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/* We expect only 2 integers (r and s) from the sequence */
|
||||
if (seq.next->next != NULL) {
|
||||
cur = seq.next;
|
||||
mbedtls_asn1_sequence *next;
|
||||
|
||||
VERBOSE("%s: nb seq != 2\n", __func__);
|
||||
/* Free all the sequences */
|
||||
while (cur != NULL) {
|
||||
next = cur->next;
|
||||
mbedtls_free(cur);
|
||||
cur = next;
|
||||
}
|
||||
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ECDSA signatures are composed of a tuple (R,S) where R and S are between 0 and n.
|
||||
* This means that the R and S can have a maximum of 32 each, but can also be smaller.
|
||||
* Also seen the integer sequence may (sometime) start with 0x00 as MSB, but we can only
|
||||
* manage exactly 2*32 bytes, we remove this higher byte if there are not 00,
|
||||
* we will fail either.
|
||||
*/
|
||||
cur = &seq;
|
||||
memset(sig, 0U, sizeof(sig));
|
||||
|
||||
while (cur != NULL) {
|
||||
size_t skip = 0U;
|
||||
size_t seek = seq_num * bignum_len;
|
||||
|
||||
if (cur->buf.len > bignum_len) {
|
||||
/* Remove extra 0x00 bytes */
|
||||
skip = cur->buf.len - bignum_len;
|
||||
} else if (cur->buf.len < bignum_len) {
|
||||
/* Add padding to match HW required size */
|
||||
seek += (bignum_len % cur->buf.len);
|
||||
}
|
||||
|
||||
if (seek + cur->buf.len > sizeof(sig) + skip) {
|
||||
panic();
|
||||
}
|
||||
|
||||
memcpy(sig + seek, cur->buf.p + skip, cur->buf.len - skip);
|
||||
cur = cur->next;
|
||||
seq_num++;
|
||||
}
|
||||
|
||||
/* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */
|
||||
mbedtls_free(seq.next);
|
||||
|
||||
/* Compute hash for the data covered by the signature */
|
||||
stm32_hash_init(HASH_SHA256);
|
||||
|
||||
ret = stm32_hash_final_update((uint8_t *)data_ptr, data_len, image_hash);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: stm32_hash_final_update (%d)\n", __func__, ret);
|
||||
return CRYPTO_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
return verify_signature(image_hash, my_pk, sig, curve_id);
|
||||
}
|
||||
|
||||
static int crypto_verify_hash(void *data_ptr, unsigned int data_len,
|
||||
void *digest_info_ptr,
|
||||
unsigned int digest_info_len)
|
||||
{
|
||||
int ret;
|
||||
uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
|
||||
unsigned char *p;
|
||||
mbedtls_md_type_t md_alg;
|
||||
size_t len;
|
||||
|
||||
/* we receive an asn1 encapsulated digest, we flatten it */
|
||||
ret = get_plain_digest_from_asn1(digest_info_ptr,
|
||||
digest_info_len, &p, &len,
|
||||
&md_alg);
|
||||
if ((ret != 0) || (md_alg != MBEDTLS_MD_SHA256) || (len != sizeof(calc_hash))) {
|
||||
return CRYPTO_ERR_HASH;
|
||||
}
|
||||
|
||||
digest_info_ptr = p;
|
||||
digest_info_len = len;
|
||||
|
||||
stm32_hash_init(HASH_SHA256);
|
||||
|
||||
ret = stm32_hash_final_update(data_ptr, data_len, calc_hash);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: hash failed\n", __func__);
|
||||
return CRYPTO_ERR_HASH;
|
||||
}
|
||||
|
||||
ret = memcmp(calc_hash, digest_info_ptr, digest_info_len);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: not expected digest\n", __func__);
|
||||
ret = CRYPTO_ERR_HASH;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(DECRYPTION_SUPPORT_none)
|
||||
static int derive_key(uint8_t *key, size_t *key_len, size_t len,
|
||||
unsigned int *flags, const uint8_t *img_id, size_t img_id_len)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
assert(*key_len >= 32U);
|
||||
|
||||
/*
|
||||
* Not a real derivation yet
|
||||
*
|
||||
* But we expect a 32 bytes key, and OTP is only 16 bytes
|
||||
* => duplicate.
|
||||
*/
|
||||
for (i = 0U, j = len; j < 32U;
|
||||
i += sizeof(uint32_t), j += sizeof(uint32_t)) {
|
||||
memcpy(key + j, key + i, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
*key_len = 32U;
|
||||
/* Variable 'key' store a real key */
|
||||
*flags = 0U;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
|
||||
size_t *key_len, unsigned int *flags,
|
||||
const uint8_t *img_id, size_t img_id_len)
|
||||
{
|
||||
uint32_t otp_idx;
|
||||
uint32_t otp_len;
|
||||
size_t read_len;
|
||||
size_t i;
|
||||
|
||||
if (fw_enc_status == FW_ENC_WITH_BSSK) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (stm32_get_otp_index(ENCKEY_OTP, &otp_idx, &otp_len) != 0) {
|
||||
VERBOSE("%s: get %s index error\n", __func__, ENCKEY_OTP);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (otp_len > (*key_len * CHAR_BIT)) {
|
||||
VERBOSE("%s: length Error otp_len=%u key_len=%u\n", __func__,
|
||||
otp_len, *key_len * CHAR_BIT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
read_len = otp_len / CHAR_BIT;
|
||||
assert(read_len % sizeof(uint32_t) == 0);
|
||||
|
||||
for (i = 0U; i < read_len / sizeof(uint32_t); i++) {
|
||||
uint32_t tmp;
|
||||
uint32_t otp_val;
|
||||
|
||||
if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
|
||||
zeromem(key, *key_len);
|
||||
VERBOSE("%s: unable to read from otp\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = bswap32(otp_val);
|
||||
memcpy(key + i * sizeof(uint32_t), &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/* Now we have the OTP values in key till read_len */
|
||||
|
||||
if (derive_key(key, key_len, read_len, flags, img_id,
|
||||
img_id_len) != 0) {
|
||||
zeromem(key, *key_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum stm32_saes_key_selection select_key(unsigned int key_flags)
|
||||
{
|
||||
if ((key_flags & ENC_KEY_IS_IDENTIFIER) != 0U) {
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Use the provided key buffer */
|
||||
return STM32_SAES_KEY_SOFT;
|
||||
}
|
||||
|
||||
static int stm32_decrypt_aes_gcm(void *data, size_t data_len,
|
||||
const void *key, unsigned int key_len,
|
||||
unsigned int key_flags,
|
||||
const void *iv, unsigned int iv_len,
|
||||
const void *tag, unsigned int tag_len)
|
||||
{
|
||||
int ret;
|
||||
struct stm32_saes_context ctx;
|
||||
unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
|
||||
enum stm32_saes_key_selection key_mode;
|
||||
unsigned int diff = 0U;
|
||||
unsigned int i;
|
||||
|
||||
key_mode = select_key(key_flags);
|
||||
|
||||
ret = stm32_saes_init(&ctx, true, STM32_SAES_MODE_GCM, key_mode, key,
|
||||
key_len, iv, iv_len);
|
||||
if (ret != 0) {
|
||||
return CRYPTO_ERR_INIT;
|
||||
}
|
||||
|
||||
ret = stm32_saes_update_assodata(&ctx, true, NULL, 0U);
|
||||
if (ret != 0) {
|
||||
return CRYPTO_ERR_DECRYPTION;
|
||||
}
|
||||
|
||||
ret = stm32_saes_update_load(&ctx, true, data, data, data_len);
|
||||
if (ret != 0) {
|
||||
return CRYPTO_ERR_DECRYPTION;
|
||||
}
|
||||
|
||||
ret = stm32_saes_final(&ctx, tag_buf, sizeof(tag_buf));
|
||||
if (ret != 0) {
|
||||
return CRYPTO_ERR_DECRYPTION;
|
||||
}
|
||||
|
||||
/* Check tag in "constant-time" */
|
||||
for (i = 0U; i < tag_len; i++) {
|
||||
diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
|
||||
}
|
||||
|
||||
if (diff != 0U) {
|
||||
return CRYPTO_ERR_DECRYPTION;
|
||||
}
|
||||
|
||||
return CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticated decryption of an image
|
||||
*
|
||||
*/
|
||||
static int crypto_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, size_t len,
|
||||
const void *key, unsigned int key_len, unsigned int key_flags,
|
||||
const void *iv, unsigned int iv_len, const void *tag,
|
||||
unsigned int tag_len)
|
||||
{
|
||||
int rc = -1;
|
||||
uint32_t real_iv[4];
|
||||
|
||||
switch (dec_algo) {
|
||||
case CRYPTO_GCM_DECRYPT:
|
||||
/*
|
||||
* GCM expect a Nonce
|
||||
* The AES IV is the nonce (a uint32_t[3])
|
||||
* then a counter (a uint32_t big endian)
|
||||
* The counter starts at 2.
|
||||
*/
|
||||
memcpy(real_iv, iv, iv_len);
|
||||
real_iv[3] = htobe32(0x2U);
|
||||
|
||||
rc = stm32_decrypt_aes_gcm(data_ptr, len, key, key_len, key_flags,
|
||||
real_iv, sizeof(real_iv), tag, tag_len);
|
||||
break;
|
||||
default:
|
||||
rc = CRYPTO_ERR_DECRYPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
REGISTER_CRYPTO_LIB("stm32_crypto_lib",
|
||||
crypto_lib_init,
|
||||
crypto_verify_signature,
|
||||
crypto_verify_hash,
|
||||
crypto_auth_decrypt);
|
||||
|
||||
#else /* No decryption support */
|
||||
REGISTER_CRYPTO_LIB("stm32_crypto_lib",
|
||||
crypto_lib_init,
|
||||
crypto_verify_signature,
|
||||
crypto_verify_hash,
|
||||
NULL);
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, STMicroelectronics - All Rights Reserved
|
||||
* Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -42,6 +42,14 @@ struct plat_io_policy policies[MAX_NUMBER_IDS] = {
|
|||
.img_type_guid = STM32MP_FIP_GUID,
|
||||
.check = open_storage
|
||||
},
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
[ENC_IMAGE_ID] = {
|
||||
.dev_handle = &fip_dev_handle,
|
||||
.image_spec = (uintptr_t)NULL,
|
||||
.img_type_guid = NULL_GUID,
|
||||
.check = open_fip
|
||||
},
|
||||
#endif
|
||||
#if STM32MP_SDMMC || STM32MP_EMMC
|
||||
[GPT_IMAGE_ID] = {
|
||||
.dev_handle = &storage_dev_handle,
|
||||
|
@ -66,7 +74,16 @@ struct plat_io_policy policies[MAX_NUMBER_IDS] = {
|
|||
#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
|
||||
};
|
||||
|
||||
#define FCONF_ST_IO_UUID_NUMBER U(8)
|
||||
#define DEFAULT_UUID_NUMBER U(7)
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
#define TBBR_UUID_NUMBER U(6)
|
||||
#else
|
||||
#define TBBR_UUID_NUMBER U(0)
|
||||
#endif
|
||||
|
||||
#define FCONF_ST_IO_UUID_NUMBER (DEFAULT_UUID_NUMBER + \
|
||||
TBBR_UUID_NUMBER)
|
||||
|
||||
static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER];
|
||||
static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids);
|
||||
|
@ -85,7 +102,14 @@ static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = {
|
|||
{BL33_IMAGE_ID, "bl33_uuid"},
|
||||
{HW_CONFIG_ID, "hw_cfg_uuid"},
|
||||
{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
|
||||
{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
{STM32MP_CONFIG_CERT_ID, "stm32mp_cfg_cert_uuid"},
|
||||
{TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
|
||||
{TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
|
||||
{NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
|
||||
{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
|
||||
{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
};
|
||||
|
||||
int fconf_populate_stm32mp_io_policies(uintptr_t config)
|
||||
|
@ -135,8 +159,20 @@ int fconf_populate_stm32mp_io_policies(uintptr_t config)
|
|||
|
||||
uuid_ptr->uuid = uuid_helper.uuid_struct;
|
||||
policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
|
||||
policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
|
||||
policies[load_info[i].image_id].check = open_fip;
|
||||
switch (load_info[i].image_id) {
|
||||
#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
|
||||
case BL32_IMAGE_ID:
|
||||
case BL32_EXTRA1_IMAGE_ID:
|
||||
case BL32_EXTRA2_IMAGE_ID:
|
||||
policies[load_info[i].image_id].dev_handle = &enc_dev_handle;
|
||||
policies[load_info[i].image_id].check = open_enc_fip;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
|
||||
policies[load_info[i].image_id].check = open_fip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
204
plat/st/common/stm32mp_trusted_boot.c
Normal file
204
plat/st/common/stm32mp_trusted_boot.c
Normal file
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/tbbr/cot_def.h>
|
||||
#include <drivers/st/stm32_hash.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <lib/fconf/fconf_dyn_cfg_getter.h>
|
||||
#include <lib/fconf/fconf_tbbr_getter.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <boot_api.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define HEADER_AND_EXT_TOTAL_SIZE 512
|
||||
|
||||
static uint8_t der_sha256_header[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
|
||||
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
|
||||
static uint8_t root_pk_hash[HASH_DER_LEN];
|
||||
|
||||
static int copy_hash_from_otp(const char *otp_name, uint8_t *hash, size_t len)
|
||||
{
|
||||
uint32_t otp_idx;
|
||||
uint32_t otp_len;
|
||||
size_t i;
|
||||
bool valid = false;
|
||||
|
||||
assert(len % sizeof(uint32_t) == 0);
|
||||
|
||||
if (stm32_get_otp_index(otp_name, &otp_idx, &otp_len) != 0) {
|
||||
VERBOSE("%s: get %s index error\n", __func__, otp_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (otp_len != (len * CHAR_BIT)) {
|
||||
VERBOSE("%s: length Error\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0U; i < len / sizeof(uint32_t); i++) {
|
||||
uint32_t tmp;
|
||||
uint32_t otp_val;
|
||||
uint32_t first;
|
||||
|
||||
if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
|
||||
VERBOSE("%s: unable to read from otp\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = bswap32(otp_val);
|
||||
memcpy(hash + i * sizeof(uint32_t), &tmp, sizeof(tmp));
|
||||
|
||||
if (i == 0U) {
|
||||
first = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if key hash values in OTP are 0 or 0xFFFFFFFFF
|
||||
* programmed : Invalid Key
|
||||
*/
|
||||
if (!stm32mp_is_closed_device() && !valid) {
|
||||
if ((tmp != 0U) && (tmp != 0xFFFFFFFFU) && (tmp != first)) {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!stm32mp_is_closed_device() && !valid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#if STM32_HEADER_VERSION_MAJOR == 1
|
||||
static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len)
|
||||
{
|
||||
if (cookie != NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return copy_hash_from_otp(PKH_OTP, hash, len);
|
||||
}
|
||||
#else
|
||||
static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len)
|
||||
{
|
||||
int ret;
|
||||
uint32_t pk_idx = 0U;
|
||||
uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
|
||||
uint8_t otp_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
|
||||
boot_api_image_header_t *hdr = (boot_api_image_header_t *)(SRAM3_BASE + SRAM3_SIZE -
|
||||
HEADER_AND_EXT_TOTAL_SIZE);
|
||||
boot_extension_header_t *ext_header = (boot_extension_header_t *)hdr->ext_header;
|
||||
boot_ext_header_params_authentication_t *param;
|
||||
|
||||
if (cookie != NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hdr->header_version != BOOT_API_HEADER_VERSION) {
|
||||
VERBOSE("%s: unexpected header_version\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
param = (boot_ext_header_params_authentication_t *)ext_header->params;
|
||||
|
||||
pk_idx = param->pk_idx;
|
||||
|
||||
stm32_hash_init(HASH_SHA256);
|
||||
ret = stm32_hash_final_update((uint8_t *)param->pk_hashes,
|
||||
param->nb_pk * sizeof(boot_api_sha256_t), calc_hash);
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: hash failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = copy_hash_from_otp(PKH_OTP, otp_hash, len);
|
||||
if (ret < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
ret = memcmp(calc_hash, otp_hash, sizeof(calc_hash));
|
||||
if (ret != 0) {
|
||||
VERBOSE("%s: not expected digest\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = sizeof(otp_hash);
|
||||
}
|
||||
|
||||
memcpy(hash, param->pk_hashes[pk_idx], sizeof(otp_hash));
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
size_t start_copy_idx = 0U;
|
||||
int res;
|
||||
|
||||
memcpy(root_pk_hash, der_sha256_header, sizeof(der_sha256_header));
|
||||
start_copy_idx = sizeof(der_sha256_header);
|
||||
|
||||
res = get_rotpk_hash(cookie, root_pk_hash + start_copy_idx,
|
||||
BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES);
|
||||
if (res < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*key_len = HASH_DER_LEN;
|
||||
*key_ptr = &root_pk_hash;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
|
||||
if ((res == 0) && !stm32mp_is_closed_device()) {
|
||||
*flags |= ROTPK_NOT_DEPLOYED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
|
||||
{
|
||||
*nv_ctr = mmio_read_32(TAMP_BASE + TAMP_COUNTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
|
||||
{
|
||||
while (mmio_read_32(TAMP_BASE + TAMP_COUNTR) != nv_ctr) {
|
||||
mmio_write_32(TAMP_BASE + TAMP_COUNTR, 1U);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
|
||||
{
|
||||
assert(heap_addr != NULL);
|
||||
assert(heap_size != NULL);
|
||||
|
||||
#if STM32MP_USE_EXTERNAL_HEAP
|
||||
/* Retrieve the already allocated heap's info from DTB */
|
||||
*heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr);
|
||||
*heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size);
|
||||
|
||||
/* We expect heap already statically mapped */
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return get_mbedtls_heap_helper(heap_addr, heap_size);
|
||||
#endif
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include <drivers/st/bsec.h>
|
||||
#include <drivers/st/regulator_fixed.h>
|
||||
#include <drivers/st/stm32_iwdg.h>
|
||||
#include <drivers/st/stm32_rng.h>
|
||||
#include <drivers/st/stm32_uart.h>
|
||||
#include <drivers/st/stm32mp1_clk.h>
|
||||
#include <drivers/st/stm32mp1_pwr.h>
|
||||
|
@ -47,10 +48,6 @@ static const char debug_msg[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if STM32MP15
|
||||
static struct stm32mp_auth_ops stm32mp1_auth_ops;
|
||||
#endif
|
||||
|
||||
static void print_reset_reason(void)
|
||||
{
|
||||
uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
|
||||
|
@ -344,6 +341,14 @@ void bl2_el3_plat_arch_setup(void)
|
|||
}
|
||||
|
||||
skip_console_init:
|
||||
#if !TRUSTED_BOARD_BOOT
|
||||
if (stm32mp_is_closed_device()) {
|
||||
/* Closed chip mandates authentication */
|
||||
ERROR("Secure chip: TRUSTED_BOARD_BOOT must be enabled\n");
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fixed_regulator_register() != 0) {
|
||||
panic();
|
||||
}
|
||||
|
@ -375,14 +380,9 @@ skip_console_init:
|
|||
}
|
||||
}
|
||||
|
||||
#if STM32MP15
|
||||
if (stm32mp_is_auth_supported()) {
|
||||
stm32mp1_auth_ops.check_key =
|
||||
boot_context->bootrom_ecdsa_check_key;
|
||||
stm32mp1_auth_ops.verify_signature =
|
||||
boot_context->bootrom_ecdsa_verify_signature;
|
||||
|
||||
stm32mp_init_auth(&stm32mp1_auth_ops);
|
||||
#if STM32MP13
|
||||
if (stm32_rng_init() != 0) {
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
19
plat/st/stm32mp1/cert_create_tbbr.mk
Normal file
19
plat/st/stm32mp1/cert_create_tbbr.mk
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Override TBBR Cert to update generic certificate
|
||||
|
||||
$(eval $(call add_define,PDEF_CERTS))
|
||||
|
||||
PLAT_INCLUDE += -I${PLAT_DIR}include
|
||||
|
||||
src/stm32mp1_tbb_cert.o: ${PLAT_DIR}stm32mp1_tbb_cert.c
|
||||
${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
|
||||
|
||||
PLAT_OBJECTS = src/stm32mp1_tbb_cert.o
|
||||
|
||||
OBJECTS += $(PLAT_OBJECTS)
|
||||
|
|
@ -232,21 +232,14 @@ typedef struct {
|
|||
#if STM32MP15
|
||||
/*
|
||||
* Pointers to bootROM External Secure Services
|
||||
* - ECDSA check key
|
||||
* - ECDSA verify signature
|
||||
* - ECDSA verify signature and go
|
||||
*/
|
||||
uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in,
|
||||
uint8_t *pubkey_out);
|
||||
uint32_t reserved3;
|
||||
uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in,
|
||||
uint8_t *pubkey_in,
|
||||
uint8_t *signature,
|
||||
uint32_t ecc_algo);
|
||||
uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in,
|
||||
uint8_t *pub_key_in,
|
||||
uint8_t *signature,
|
||||
uint32_t ecc_algo,
|
||||
uint32_t *entry_in);
|
||||
uint32_t reserved4;
|
||||
#endif
|
||||
/*
|
||||
* Information specific to an SD boot
|
||||
|
@ -340,6 +333,8 @@ typedef struct {
|
|||
uint32_t binary_type;
|
||||
/* Pad up to 128 byte total size */
|
||||
uint8_t pad[16];
|
||||
/* Followed by extension header */
|
||||
uint8_t ext_header[];
|
||||
#endif
|
||||
#if STM32MP15
|
||||
/*
|
||||
|
@ -370,4 +365,45 @@ typedef struct {
|
|||
#endif
|
||||
} __packed boot_api_image_header_t;
|
||||
|
||||
typedef uint8_t boot_api_sha256_t[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
|
||||
|
||||
typedef struct {
|
||||
/* Extension header type:
|
||||
* BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB or
|
||||
* BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB
|
||||
* BOOT_API_PADDING_HEADER_MAGIC_NB
|
||||
*/
|
||||
uint32_t type;
|
||||
/* Extension header len in byte */
|
||||
uint32_t len;
|
||||
/* parameters of this extension */
|
||||
uint8_t params[];
|
||||
} __packed boot_extension_header_t;
|
||||
|
||||
typedef struct {
|
||||
/* Idx of ECDSA public key to be used in table */
|
||||
uint32_t pk_idx;
|
||||
/* Number of ECDSA public key in table */
|
||||
uint32_t nb_pk;
|
||||
/*
|
||||
* Type of ECC algorithm to use :
|
||||
* value 1 : for P-256 NIST algorithm
|
||||
* value 2 : for Brainpool 256 algorithm
|
||||
* See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
|
||||
*/
|
||||
uint32_t ecc_algo_type;
|
||||
/* ECDSA public key to be used to check signature. */
|
||||
uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
|
||||
/* table of Hash of Algo+ECDSA public key */
|
||||
boot_api_sha256_t pk_hashes[];
|
||||
} __packed boot_ext_header_params_authentication_t;
|
||||
|
||||
typedef struct {
|
||||
/* Size of encryption key (128 or 256) */
|
||||
uint32_t key_size;
|
||||
uint32_t derivation_cont;
|
||||
/* 128 msb bits of plain payload SHA256 */
|
||||
uint32_t hash[4];
|
||||
} __packed boot_ext_header_params_encrypted_fsbl_t;
|
||||
|
||||
#endif /* BOOT_API_H */
|
||||
|
|
14
plat/st/stm32mp1/include/plat_def_fip_uuid.h
Normal file
14
plat/st/stm32mp1/include/plat_def_fip_uuid.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_DEF_FIP_UUID_H
|
||||
#define PLAT_DEF_FIP_UUID_H
|
||||
|
||||
#define UUID_STM32MP_CONFIG_CERT \
|
||||
{{0x50, 0x1d, 0x8d, 0xd2}, {0x8b, 0xce}, {0x49, 0xa5}, 0x84, 0xeb, \
|
||||
{0x55, 0x9a, 0x9f, 0x2e, 0xae, 0xaf} }
|
||||
#endif /* PLAT_DEF_FIP_UUID_H */
|
||||
|
40
plat/st/stm32mp1/include/plat_tbbr_img_def.h
Normal file
40
plat/st/stm32mp1/include/plat_tbbr_img_def.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STM32MP1_IMG_DEF_H
|
||||
#define STM32MP1_IMG_DEF_H
|
||||
|
||||
#include <export/common/tbbr/tbbr_img_def_exp.h>
|
||||
|
||||
/* Undef the existing values */
|
||||
#undef BL32_EXTRA1_IMAGE_ID
|
||||
#undef BL32_EXTRA2_IMAGE_ID
|
||||
#undef TOS_FW_CONFIG_ID
|
||||
#undef TRUSTED_BOOT_FW_CERT_ID
|
||||
#undef FWU_METADATA_IMAGE_ID
|
||||
#undef BKUP_FWU_METADATA_IMAGE_ID
|
||||
#undef FW_CONFIG_ID
|
||||
#undef HW_CONFIG_ID
|
||||
#undef GPT_IMAGE_ID
|
||||
#undef ENC_IMAGE_ID
|
||||
|
||||
/* Define the STM32MP1 used ID */
|
||||
#define FW_CONFIG_ID U(1)
|
||||
#define HW_CONFIG_ID U(2)
|
||||
#define GPT_IMAGE_ID U(3)
|
||||
#define ENC_IMAGE_ID U(6)
|
||||
#define BL32_EXTRA1_IMAGE_ID U(8)
|
||||
#define BL32_EXTRA2_IMAGE_ID U(9)
|
||||
#define FWU_METADATA_IMAGE_ID U(12)
|
||||
#define BKUP_FWU_METADATA_IMAGE_ID U(13)
|
||||
#define TOS_FW_CONFIG_ID U(16)
|
||||
#define STM32MP_CONFIG_CERT_ID U(17)
|
||||
|
||||
/* Increase the MAX_NUMBER_IDS to match the authentication pool required */
|
||||
#define MAX_NUMBER_IDS U(19)
|
||||
|
||||
#endif /* STM32MP1_IMG_DEF_H */
|
119
plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
Normal file
119
plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
#define MBEDTLS_CONFIG_H
|
||||
|
||||
/*
|
||||
* Key algorithms currently supported on mbed TLS libraries
|
||||
*/
|
||||
#define TF_MBEDTLS_USE_RSA 0
|
||||
#define TF_MBEDTLS_USE_ECDSA 1
|
||||
|
||||
/*
|
||||
* Hash algorithms currently supported on mbed TLS libraries
|
||||
*/
|
||||
#define TF_MBEDTLS_SHA256 1
|
||||
#define TF_MBEDTLS_SHA384 2
|
||||
#define TF_MBEDTLS_SHA512 3
|
||||
|
||||
/*
|
||||
* Configuration file to build mbed TLS with the required features for
|
||||
* Trusted Boot
|
||||
*/
|
||||
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */
|
||||
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
|
||||
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
|
||||
#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
|
||||
#define MBEDTLS_X509_CHECK_KEY_USAGE
|
||||
#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
|
||||
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
|
||||
#define MBEDTLS_ERROR_C
|
||||
#define MBEDTLS_MD_C
|
||||
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_OID_C
|
||||
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PK_WRITE_C
|
||||
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
|
||||
#if TF_MBEDTLS_USE_ECDSA
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_NO_INTERNAL_RNG
|
||||
#endif
|
||||
#if TF_MBEDTLS_USE_RSA
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_SHA256_C
|
||||
#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256)
|
||||
#define MBEDTLS_SHA512_C
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_VERSION_C
|
||||
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
|
||||
#if TF_MBEDTLS_USE_AES_GCM
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_GCM_C
|
||||
#endif
|
||||
|
||||
/* MPI / BIGNUM options */
|
||||
#define MBEDTLS_MPI_WINDOW_SIZE 2
|
||||
|
||||
#if TF_MBEDTLS_USE_RSA
|
||||
#if TF_MBEDTLS_KEY_SIZE <= 2048
|
||||
#define MBEDTLS_MPI_MAX_SIZE 256
|
||||
#else
|
||||
#define MBEDTLS_MPI_MAX_SIZE 512
|
||||
#endif
|
||||
#else
|
||||
#define MBEDTLS_MPI_MAX_SIZE 256
|
||||
#endif
|
||||
|
||||
/* Memory buffer allocator options */
|
||||
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8
|
||||
|
||||
/*
|
||||
* Prevent the use of 128-bit division which
|
||||
* creates dependency on external libraries.
|
||||
*/
|
||||
#define MBEDTLS_NO_UDBL_DIVISION
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* System headers required to build mbed TLS with the current configuration */
|
||||
#include <stdlib.h>
|
||||
#include <mbedtls/check_config.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Mbed TLS heap size is smal as we only use the asn1
|
||||
* parsing functions
|
||||
* digest, signature and crypto algorithm are done by
|
||||
* other library.
|
||||
*/
|
||||
|
||||
#define TF_MBEDTLS_HEAP_SIZE U(5120)
|
||||
#endif /* MBEDTLS_CONFIG_H */
|
19
plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
Normal file
19
plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef STM32MP1_TBB_CERT_H
|
||||
#define STM32MP1_TBB_CERT_H
|
||||
|
||||
#include <tbbr/tbb_cert.h>
|
||||
|
||||
/*
|
||||
* Enumerate the certificates that are used to establish the chain of trust
|
||||
*/
|
||||
enum {
|
||||
STM32MP_CONFIG_CERT = FWU_CERT + 1
|
||||
};
|
||||
|
||||
#endif /* STM32MP1_TBB_CERT_H */
|
18
plat/st/stm32mp1/plat_def_uuid_config.c
Normal file
18
plat/st/stm32mp1/plat_def_uuid_config.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <firmware_image_package.h>
|
||||
|
||||
#include "tbbr_config.h"
|
||||
|
||||
toc_entry_t plat_def_toc_entries[] = {
|
||||
{
|
||||
.name = "STM32MP CONFIG CERT",
|
||||
.uuid = UUID_STM32MP_CONFIG_CERT,
|
||||
.cmdline_name = "stm32mp-cfg-cert"
|
||||
}
|
||||
};
|
||||
|
25
plat/st/stm32mp1/plat_fiptool.mk
Normal file
25
plat/st/stm32mp1/plat_fiptool.mk
Normal file
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Name of the platform defined source file name,
|
||||
# which contains platform defined UUID entries populated
|
||||
# in the plat_def_toc_entries[].
|
||||
PLAT_DEF_UUID_FILE_NAME := plat_def_uuid_config
|
||||
|
||||
INCLUDE_PATHS += -I${PLAT_DIR}/include -I./
|
||||
|
||||
PLAT_DEF_UUID := yes
|
||||
|
||||
ifeq (${PLAT_DEF_UUID},yes)
|
||||
HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
|
||||
|
||||
${PLAT_DEF_UUID_FILE_NAME}.o: ${PLAT_DIR}${PLAT_DEF_UUID_FILE_NAME}.c
|
||||
${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
|
||||
|
||||
PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o
|
||||
endif
|
||||
|
||||
OBJECTS += ${PLAT_OBJECTS}
|
|
@ -18,6 +18,12 @@ STM32MP_UART_BAUDRATE ?= 115200
|
|||
# If it is set to 0, then FIP is used
|
||||
STM32MP_USE_STM32IMAGE ?= 0
|
||||
|
||||
TRUSTED_BOARD_BOOT ?= 0
|
||||
STM32MP_USE_EXTERNAL_HEAP ?= 0
|
||||
|
||||
# Use secure library from the ROM code for authentication
|
||||
STM32MP_CRYPTO_ROM_LIB ?= 0
|
||||
|
||||
# Please don't increment this value without good understanding of
|
||||
# the monotonic counter
|
||||
STM32_TF_VERSION ?= 0
|
||||
|
@ -49,10 +55,19 @@ STM32MP15 := 1
|
|||
endif
|
||||
|
||||
ifeq ($(STM32MP13),1)
|
||||
# Will use SRAM2 as mbedtls heap
|
||||
STM32MP_USE_EXTERNAL_HEAP := 1
|
||||
|
||||
# DDR controller with single AXI port and 16-bit interface
|
||||
STM32MP_DDR_DUAL_AXI_PORT:= 0
|
||||
STM32MP_DDR_32BIT_INTERFACE:= 0
|
||||
|
||||
ifeq (${TRUSTED_BOARD_BOOT},1)
|
||||
# PKA algo to include
|
||||
PKA_USE_NIST_P256 := 1
|
||||
PKA_USE_BRAINPOOL_P256T1:= 1
|
||||
endif
|
||||
|
||||
# STM32 image header version v2.0
|
||||
STM32_HEADER_VERSION_MAJOR:= 2
|
||||
STM32_HEADER_VERSION_MINOR:= 0
|
||||
|
@ -70,6 +85,13 @@ STM32_HEADER_VERSION_MINOR:= 0
|
|||
# Add OP-TEE reserved shared memory area in mapping
|
||||
STM32MP15_OPTEE_RSV_SHM := 1
|
||||
$(eval $(call add_defines,STM32MP15_OPTEE_RSV_SHM))
|
||||
|
||||
STM32MP_CRYPTO_ROM_LIB := 1
|
||||
|
||||
# Decryption support
|
||||
ifneq ($(DECRYPTION_SUPPORT),none)
|
||||
$(error "DECRYPTION_SUPPORT not supported on STM32MP15")
|
||||
endif
|
||||
endif
|
||||
|
||||
# STM32 image header binary type for BL2
|
||||
|
@ -110,6 +132,14 @@ $(error FWU Feature enabled only with FIP images)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(STM32MP13),1)
|
||||
STM32_HASH_VER := 4
|
||||
STM32_RNG_VER := 4
|
||||
else # Assuming STM32MP15
|
||||
STM32_HASH_VER := 2
|
||||
STM32_RNG_VER := 2
|
||||
endif
|
||||
|
||||
# Boot devices
|
||||
STM32MP_EMMC ?= 0
|
||||
STM32MP_SDMMC ?= 0
|
||||
|
@ -184,6 +214,11 @@ endif
|
|||
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
|
||||
# Add the HW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
|
||||
ifeq ($(GENERATE_COT),1)
|
||||
STM32MP_CFG_CERT := $(BUILD_PLAT)/stm32mp_cfg_cert.crt
|
||||
# Add the STM32MP_CFG_CERT to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_CFG_CERT},--stm32mp-cfg-cert))
|
||||
endif
|
||||
ifeq ($(AARCH32_SP),sp_min)
|
||||
STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
|
||||
|
@ -191,10 +226,10 @@ else
|
|||
# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
|
||||
# in the FIP if the platform requires.
|
||||
ifneq ($(BL32_EXTRA1),)
|
||||
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
|
||||
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
|
||||
endif
|
||||
ifneq ($(BL32_EXTRA2),)
|
||||
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
|
||||
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -202,7 +237,11 @@ endif
|
|||
# Enable flags for C files
|
||||
$(eval $(call assert_booleans,\
|
||||
$(sort \
|
||||
PKA_USE_BRAINPOOL_P256T1 \
|
||||
PKA_USE_NIST_P256 \
|
||||
PLAT_TBBR_IMG_DEF \
|
||||
PLAT_XLAT_TABLES_DYNAMIC \
|
||||
STM32MP_CRYPTO_ROM_LIB \
|
||||
STM32MP_DDR_32BIT_INTERFACE \
|
||||
STM32MP_DDR_DUAL_AXI_PORT \
|
||||
STM32MP_EARLY_CONSOLE \
|
||||
|
@ -215,6 +254,7 @@ $(eval $(call assert_booleans,\
|
|||
STM32MP_SPI_NOR \
|
||||
STM32MP_UART_PROGRAMMER \
|
||||
STM32MP_USB_PROGRAMMER \
|
||||
STM32MP_USE_EXTERNAL_HEAP \
|
||||
STM32MP_USE_STM32IMAGE \
|
||||
STM32MP13 \
|
||||
STM32MP15 \
|
||||
|
@ -223,6 +263,9 @@ $(eval $(call assert_booleans,\
|
|||
$(eval $(call assert_numerics,\
|
||||
$(sort \
|
||||
PLAT_PARTITION_MAX_ENTRIES \
|
||||
STM32_HASH_VER \
|
||||
STM32_HEADER_VERSION_MAJOR \
|
||||
STM32_RNG_VER \
|
||||
STM32_TF_A_COPIES \
|
||||
STM32_TF_VERSION \
|
||||
STM32MP_UART_BAUDRATE \
|
||||
|
@ -231,10 +274,17 @@ $(eval $(call assert_numerics,\
|
|||
$(eval $(call add_defines,\
|
||||
$(sort \
|
||||
DWL_BUFFER_BASE \
|
||||
PKA_USE_BRAINPOOL_P256T1 \
|
||||
PKA_USE_NIST_P256 \
|
||||
PLAT_PARTITION_MAX_ENTRIES \
|
||||
PLAT_TBBR_IMG_DEF \
|
||||
PLAT_XLAT_TABLES_DYNAMIC \
|
||||
STM32_HASH_VER \
|
||||
STM32_HEADER_VERSION_MAJOR \
|
||||
STM32_RNG_VER \
|
||||
STM32_TF_A_COPIES \
|
||||
STM32_TF_VERSION \
|
||||
STM32MP_CRYPTO_ROM_LIB \
|
||||
STM32MP_DDR_32BIT_INTERFACE \
|
||||
STM32MP_DDR_DUAL_AXI_PORT \
|
||||
STM32MP_EARLY_CONSOLE \
|
||||
|
@ -248,6 +298,7 @@ $(eval $(call add_defines,\
|
|||
STM32MP_UART_BAUDRATE \
|
||||
STM32MP_UART_PROGRAMMER \
|
||||
STM32MP_USB_PROGRAMMER \
|
||||
STM32MP_USE_EXTERNAL_HEAP \
|
||||
STM32MP_USE_STM32IMAGE \
|
||||
STM32MP13 \
|
||||
STM32MP15 \
|
||||
|
@ -302,7 +353,8 @@ PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \
|
|||
|
||||
ifeq ($(STM32MP13),1)
|
||||
PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \
|
||||
drivers/st/clk/clk-stm32mp13.c
|
||||
drivers/st/clk/clk-stm32mp13.c \
|
||||
drivers/st/crypto/stm32_rng.c
|
||||
else
|
||||
PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c
|
||||
endif
|
||||
|
@ -340,9 +392,47 @@ BL2_SOURCES += drivers/io/io_block.c \
|
|||
drivers/st/crypto/stm32_hash.c \
|
||||
plat/st/stm32mp1/bl2_plat_setup.c
|
||||
|
||||
ifneq (${DECRYPTION_SUPPORT},none)
|
||||
BL2_SOURCES += drivers/io/io_encrypted.c
|
||||
endif
|
||||
|
||||
ifeq ($(STM32MP15),1)
|
||||
BL2_SOURCES += plat/st/common/stm32mp_auth.c
|
||||
ifeq (${TRUSTED_BOARD_BOOT},1)
|
||||
AUTH_SOURCES := drivers/auth/auth_mod.c \
|
||||
drivers/auth/crypto_mod.c \
|
||||
drivers/auth/img_parser_mod.c
|
||||
|
||||
ifeq (${GENERATE_COT},1)
|
||||
TFW_NVCTR_VAL := 0
|
||||
NTFW_NVCTR_VAL := 0
|
||||
KEY_SIZE :=
|
||||
KEY_ALG := ecdsa
|
||||
HASH_ALG := sha256
|
||||
|
||||
ifeq (${SAVE_KEYS},1)
|
||||
TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/trusted.pem
|
||||
NON_TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/non-trusted.pem
|
||||
BL32_KEY ?= ${BUILD_PLAT}/trusted_os.pem
|
||||
BL33_KEY ?= ${BUILD_PLAT}/non-trusted_os.pem
|
||||
endif
|
||||
|
||||
endif
|
||||
TF_MBEDTLS_KEY_ALG := ecdsa
|
||||
MBEDTLS_CONFIG_FILE ?= "<stm32mp1_mbedtls_config.h>"
|
||||
|
||||
include drivers/auth/mbedtls/mbedtls_x509.mk
|
||||
|
||||
COT_DESC_IN_DTB := 1
|
||||
AUTH_SOURCES += lib/fconf/fconf_cot_getter.c \
|
||||
lib/fconf/fconf_tbbr_getter.c \
|
||||
plat/st/common/stm32mp_crypto_lib.c
|
||||
|
||||
ifeq ($(STM32MP13),1)
|
||||
AUTH_SOURCES += drivers/st/crypto/stm32_pka.c
|
||||
AUTH_SOURCES += drivers/st/crypto/stm32_saes.c
|
||||
endif
|
||||
|
||||
BL2_SOURCES += $(AUTH_SOURCES) \
|
||||
plat/st/common/stm32mp_trusted_boot.c
|
||||
endif
|
||||
|
||||
ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <drivers/st/stm32mp1_clk.h>
|
||||
|
||||
#include <boot_api.h>
|
||||
#include <stm32mp_auth.h>
|
||||
#include <stm32mp_common.h>
|
||||
#include <stm32mp_dt.h>
|
||||
#include <stm32mp1_dbgmcu.h>
|
||||
|
@ -451,6 +450,8 @@ enum ddr_type {
|
|||
#endif
|
||||
#define MONOTONIC_OTP "monotonic_otp"
|
||||
#define UID_OTP "uid_otp"
|
||||
#define PKH_OTP "pkh_otp"
|
||||
#define ENCKEY_OTP "enckey_otp"
|
||||
#define BOARD_ID_OTP "board_id"
|
||||
|
||||
/* OTP mask */
|
||||
|
@ -551,6 +552,7 @@ enum ddr_type {
|
|||
******************************************************************************/
|
||||
#define TAMP_BASE U(0x5C00A000)
|
||||
#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
|
||||
#define TAMP_COUNTR U(0x40)
|
||||
|
||||
#if !(defined(__LINKER__) || defined(__ASSEMBLER__))
|
||||
static inline uintptr_t tamp_bkpr(uint32_t idx)
|
||||
|
|
|
@ -15,14 +15,36 @@
|
|||
#define STM32MP_DDR_SHMEM_SIZE U(0) /* empty */
|
||||
#endif
|
||||
|
||||
#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP
|
||||
#if STM32MP15
|
||||
#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */
|
||||
#define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */
|
||||
#endif /* STM32MP15 */
|
||||
#else /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
|
||||
#if STM32MP13
|
||||
#if BL2_IN_XIP_MEM
|
||||
#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */
|
||||
#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */
|
||||
#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */
|
||||
#else
|
||||
/* STM32MP_BL2_RO_SIZE not used if !BL2_IN_XIP_MEM */
|
||||
#define STM32MP_BL2_SIZE U(0x0001B000) /* 108KB for BL2 */
|
||||
/* with 20KB for DTB, SYSRAM is full */
|
||||
#endif
|
||||
#endif /* STM32MP13 */
|
||||
#if STM32MP15
|
||||
#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */
|
||||
#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */
|
||||
#endif /* STM32MP15 */
|
||||
#endif /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
|
||||
|
||||
#if STM32MP13
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
|
||||
#else /* TRUSTED_BOARD_BOOT */
|
||||
#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
#endif /* STM32MP13 */
|
||||
#if STM32MP15
|
||||
#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */
|
||||
#endif /* STM32MP15 */
|
||||
#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */
|
||||
|
|
37
plat/st/stm32mp1/stm32mp1_tbb_cert.c
Normal file
37
plat/st/stm32mp1/stm32mp1_tbb_cert.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "tbbr/tbb_ext.h"
|
||||
#include "tbbr/tbb_key.h"
|
||||
|
||||
#include "tbbr/stm32mp1_tbb_cert.h"
|
||||
|
||||
/*
|
||||
* Certificates used in the chain of trust
|
||||
*
|
||||
* The order of the certificates must follow the enumeration specified in
|
||||
* stm32mp1_tbb_cert.h. All certificates are self-signed, so the issuer certificate
|
||||
* field points to itself.
|
||||
*/
|
||||
static cert_t stm32mp1_tbb_certs[] = {
|
||||
[0] = {
|
||||
.id = STM32MP_CONFIG_CERT,
|
||||
.opt = "stm32mp-cfg-cert",
|
||||
.help_msg = "STM32MP Config Certificate (output file)",
|
||||
.fn = NULL,
|
||||
.cn = "STM32MP config FW Certificate",
|
||||
.key = ROT_KEY,
|
||||
.issuer = STM32MP_CONFIG_CERT,
|
||||
.ext = {
|
||||
TRUSTED_FW_NVCOUNTER_EXT,
|
||||
HW_CONFIG_HASH_EXT,
|
||||
FW_CONFIG_HASH_EXT
|
||||
},
|
||||
.num_ext = 3
|
||||
},
|
||||
};
|
||||
|
||||
PLAT_REGISTER_COT(stm32mp1_tbb_certs);
|
|
@ -22,7 +22,9 @@ enum {
|
|||
enum {
|
||||
KEY_ALG_RSA, /* RSA PSS as defined by PKCS#1 v2.1 (default) */
|
||||
#ifndef OPENSSL_NO_EC
|
||||
KEY_ALG_ECDSA,
|
||||
KEY_ALG_ECDSA_NIST,
|
||||
KEY_ALG_ECDSA_BRAINPOOL_R,
|
||||
KEY_ALG_ECDSA_BRAINPOOL_T,
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
KEY_ALG_MAX_NUM
|
||||
};
|
||||
|
@ -42,7 +44,9 @@ enum{
|
|||
static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = {
|
||||
{ 2048, 1024, 3072, 4096 }, /* KEY_ALG_RSA */
|
||||
#ifndef OPENSSL_NO_EC
|
||||
{} /* KEY_ALG_ECDSA */
|
||||
{}, /* KEY_ALG_ECDSA_NIST */
|
||||
{}, /* KEY_ALG_ECDSA_BRAINPOOL_R */
|
||||
{} /* KEY_ALG_ECDSA_BRAINPOOL_T */
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
};
|
||||
|
||||
|
|
|
@ -93,20 +93,39 @@ err2:
|
|||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int key_create_ecdsa(key_t *key, int key_bits)
|
||||
{
|
||||
#if USING_OPENSSL3
|
||||
EVP_PKEY *ec = EVP_EC_gen("prime256v1");
|
||||
static int key_create_ecdsa(key_t *key, int key_bits, const char *curve)
|
||||
{
|
||||
EVP_PKEY *ec = EVP_EC_gen(curve);
|
||||
if (ec == NULL) {
|
||||
printf("Cannot generate EC key\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
key->key = ec;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int key_create_ecdsa_nist(key_t *key, int key_bits)
|
||||
{
|
||||
return key_create_ecdsa(key, key_bits, "prime256v1");
|
||||
}
|
||||
|
||||
static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
|
||||
{
|
||||
return key_create_ecdsa(key, key_bits, "brainpoolP256r1");
|
||||
}
|
||||
|
||||
static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
|
||||
{
|
||||
return key_create_ecdsa(key, key_bits, "brainpoolP256t1");
|
||||
}
|
||||
#else
|
||||
static int key_create_ecdsa(key_t *key, int key_bits, const int curve_id)
|
||||
{
|
||||
EC_KEY *ec;
|
||||
|
||||
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
ec = EC_KEY_new_by_curve_name(curve_id);
|
||||
if (ec == NULL) {
|
||||
printf("Cannot create EC key\n");
|
||||
return 0;
|
||||
|
@ -127,15 +146,32 @@ static int key_create_ecdsa(key_t *key, int key_bits)
|
|||
err:
|
||||
EC_KEY_free(ec);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int key_create_ecdsa_nist(key_t *key, int key_bits)
|
||||
{
|
||||
return key_create_ecdsa(key, key_bits, NID_X9_62_prime256v1);
|
||||
}
|
||||
|
||||
static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
|
||||
{
|
||||
return key_create_ecdsa(key, key_bits, NID_brainpoolP256r1);
|
||||
}
|
||||
|
||||
static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
|
||||
{
|
||||
return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1);
|
||||
}
|
||||
#endif /* USING_OPENSSL3 */
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
|
||||
typedef int (*key_create_fn_t)(key_t *key, int key_bits);
|
||||
static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
|
||||
key_create_rsa, /* KEY_ALG_RSA */
|
||||
[KEY_ALG_RSA] = key_create_rsa,
|
||||
#ifndef OPENSSL_NO_EC
|
||||
key_create_ecdsa, /* KEY_ALG_ECDSA */
|
||||
[KEY_ALG_ECDSA_NIST] = key_create_ecdsa_nist,
|
||||
[KEY_ALG_ECDSA_BRAINPOOL_R] = key_create_ecdsa_brainpool_r,
|
||||
[KEY_ALG_ECDSA_BRAINPOOL_T] = key_create_ecdsa_brainpool_t,
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
};
|
||||
|
||||
|
|
|
@ -84,7 +84,9 @@ static char *strdup(const char *str)
|
|||
static const char *key_algs_str[] = {
|
||||
[KEY_ALG_RSA] = "rsa",
|
||||
#ifndef OPENSSL_NO_EC
|
||||
[KEY_ALG_ECDSA] = "ecdsa"
|
||||
[KEY_ALG_ECDSA_NIST] = "ecdsa",
|
||||
[KEY_ALG_ECDSA_BRAINPOOL_R] = "ecdsa-brainpool-regular",
|
||||
[KEY_ALG_ECDSA_BRAINPOOL_T] = "ecdsa-brainpool-twisted",
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
};
|
||||
|
||||
|
@ -106,7 +108,7 @@ static void print_help(const char *cmd, const struct option *long_opt)
|
|||
|
||||
printf("\n\n");
|
||||
printf("The certificate generation tool loads the binary images and\n"
|
||||
"optionally the RSA keys, and outputs the key and content\n"
|
||||
"optionally the RSA or ECC keys, and outputs the key and content\n"
|
||||
"certificates properly signed to implement the chain of trust.\n"
|
||||
"If keys are provided, they must be in PEM format.\n"
|
||||
"Certificates are generated in DER format.\n");
|
||||
|
@ -267,7 +269,8 @@ static const cmd_opt_t common_cmd_opt[] = {
|
|||
},
|
||||
{
|
||||
{ "key-alg", required_argument, NULL, 'a' },
|
||||
"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
|
||||
"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, " \
|
||||
"'ecdsa', 'ecdsa-brainpool-regular', 'ecdsa-brainpool-twisted'"
|
||||
},
|
||||
{
|
||||
{ "key-size", required_argument, NULL, 'b' },
|
||||
|
|
Loading…
Add table
Reference in a new issue