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:
Manish Pandey 2022-11-14 14:11:55 +01:00 committed by TrustedFirmware Code Review
commit c3170fd80b
49 changed files with 3856 additions and 228 deletions

View file

@ -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}

View file

@ -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 | |
+--------------------------------+-------------+---------+---------------------------------------------------------+
--------------

View file

@ -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.

View file

@ -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)
-------------------------------------------------------

View file

@ -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
~~~~~~~~~~~~~~~~~~~~

View file

@ -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'
*

View file

@ -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;

View file

@ -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) {

View 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;
}

View 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();
}

View 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;
}

View file

@ -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);

View 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;
};
};

View file

@ -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
};

View file

@ -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

View file

@ -176,7 +176,7 @@
};
&pka {
secure-status = "okay";
status = "okay";
};
&pwr_regulators {
@ -298,7 +298,7 @@
};
&saes {
secure-status = "okay";
status = "okay";
};
&sdmmc1 {

View file

@ -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 */
};

View file

@ -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;

View file

@ -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

View file

@ -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);

View 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 */

View 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 */

View 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

View file

@ -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,

View file

@ -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);

View file

@ -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:

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}

View 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, &params);
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

View file

@ -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;

View 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
}

View file

@ -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

View 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)

View file

@ -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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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"
}
};

View 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}

View file

@ -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}),)

View file

@ -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)

View file

@ -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 */

View 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);

View file

@ -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 */
};

View file

@ -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 */
};

View file

@ -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' },