Merge changes from topic "mb/trusted-boot-update" into integration

* changes:
  refactor(auth)!: unify REGISTER_CRYPTO_LIB
  refactor(auth): replace plat_convert_pk
  docs(auth): add auth_decrypt in CM chapter
  feat(auth): compare platform and certificate ROTPK for authentication
  docs(auth): add 'calc_hash' function's details in CM
This commit is contained in:
Sandrine Bailleux 2023-04-24 15:46:26 +02:00 committed by TrustedFirmware Code Review
commit 7c7e7b621a
11 changed files with 157 additions and 134 deletions

View File

@ -236,18 +236,56 @@ functions must be provided by the CL:
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len);
int (*calc_hash)(enum crypto_md_algo alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE])
int (*verify_hash)(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
int (*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);
These functions are registered in the CM using the macro:
.. code:: c
REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash);
REGISTER_CRYPTO_LIB(_name,
_init,
_verify_signature,
_calc_hash,
_verify_hash,
_auth_decrypt,
_convert_pk);
``_name`` must be a string containing the name of the CL. This name is used for
debugging purposes.
Crypto module provides a function ``_calc_hash`` to calculate and
return the hash of the given data using the provided hash algorithm.
This function is mainly used in the ``MEASURED_BOOT`` and ``DRTM_SUPPORT``
features to calculate the hashes of various images/data.
Optionally, a platform function can be provided to convert public key
(_convert_pk). It is only used if the platform saves a hash of the ROTPK.
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.
.. code:: c
int (*convert_pk)(void *full_pk_ptr, unsigned int full_pk_len,
void **hashed_pk_ptr, unsigned int *hashed_pk_len);
- ``full_pk_ptr``: Pointer to Distinguished Encoding Rules (DER) ROTPK.
- ``full_pk_len``: DER ROTPK size.
- ``hashed_pk_ptr``: to return a pointer to a buffer, which hash should be the one saved in OTP.
- ``hashed_pk_len``: previous buffer size
Image Parser Module (IPM)
^^^^^^^^^^^^^^^^^^^^^^^^^
@ -936,7 +974,7 @@ i.e. verify a hash or a digital signature. Arm platforms will use a library
based on mbed TLS, which can be found in
``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the
authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports
four functions:
below functions:
.. code:: c
@ -945,6 +983,9 @@ four functions:
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len);
int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE])
int verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
@ -975,6 +1016,6 @@ The mbedTLS library algorithm support is configured by both the
--------------
*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.*
*Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.*
.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a

View File

@ -894,34 +894,6 @@ 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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -31,8 +31,6 @@
} 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,
const auth_param_type_desc_t *b)
@ -150,8 +148,8 @@ static int auth_signature(const auth_method_param_sig_t *param,
const auth_img_desc_t *img_desc,
void *img, unsigned int img_len)
{
void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr;
unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len;
void *data_ptr, *pk_ptr, *pk_plat_ptr, *sig_ptr, *sig_alg_ptr;
unsigned int data_len, pk_len, pk_plat_len, sig_len, sig_alg_len;
unsigned int flags = 0;
int rc = 0;
@ -173,51 +171,68 @@ static int auth_signature(const auth_method_param_sig_t *param,
/* Get the public key from the parent. If there is no parent (NULL),
* the certificate has been signed with the ROTPK, so we have to get
* the PK from the platform */
if (img_desc->parent) {
if (img_desc->parent != NULL) {
rc = auth_get_param(param->pk, img_desc->parent,
&pk_ptr, &pk_len);
return_if_error(rc);
} else {
rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len,
&flags);
}
/*
* Root certificates are signed with the ROTPK, so we have to
* get it from the platform.
*/
rc = plat_get_rotpk_info(param->pk->cookie, &pk_plat_ptr,
&pk_plat_len, &flags);
return_if_error(rc);
if (flags & (ROTPK_IS_HASH | ROTPK_NOT_DEPLOYED)) {
/* If the PK is a hash of the key or if the ROTPK is not
deployed on the platform, retrieve the key from the image */
pk_hash_ptr = pk_ptr;
pk_hash_len = pk_len;
assert(is_rotpk_flags_valid(flags));
/* Also retrieve the key from the image. */
rc = img_parser_get_auth_param(img_desc->img_type,
param->pk, img, img_len,
&pk_ptr, &pk_len);
return_if_error(rc);
/* Ask the crypto module to verify the signature */
rc = crypto_mod_verify_signature(data_ptr, data_len,
sig_ptr, sig_len,
sig_alg_ptr, sig_alg_len,
pk_ptr, pk_len);
return_if_error(rc);
if (flags & ROTPK_NOT_DEPLOYED) {
/*
* Validate the certificate's key against the platform ROTPK.
*
* Platform may store key in one of the following way -
* 1. Hash of ROTPK
* 2. Hash if prefixed, suffixed or modified ROTPK
* 3. Full ROTPK
*/
if ((flags & ROTPK_NOT_DEPLOYED) != 0U) {
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);
} else if ((flags & ROTPK_IS_HASH) != 0U) {
/*
* platform may store the hash of a prefixed,
* suffixed or modified pk
*/
rc = crypto_mod_convert_pk(pk_ptr, pk_len, &pk_ptr, &pk_len);
return_if_error(rc);
/* Ask the crypto-module to verify the key hash */
/*
* The hash of the certificate's public key must match
* the hash of the ROTPK.
*/
rc = crypto_mod_verify_hash(pk_ptr, pk_len,
pk_hash_ptr, pk_hash_len);
}
pk_plat_ptr, pk_plat_len);
return_if_error(rc);
} else {
/* Platform supports full ROTPK */
if ((pk_len != pk_plat_len) ||
(memcmp(pk_plat_ptr, pk_ptr, pk_len) != 0)) {
ERROR("plat and cert ROTPK len mismatch\n");
return -1;
}
}
}
/* Ask the crypto module to verify the signature */
rc = crypto_mod_verify_signature(data_ptr, data_len,
sig_ptr, sig_len,
sig_alg_ptr, sig_alg_len,
pk_ptr, pk_len);
}
return rc;
}
@ -314,15 +329,6 @@ 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-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -142,6 +142,20 @@ int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
int crypto_mod_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
void **hashed_pk_ptr, unsigned int *hashed_pk_len)
{
if (crypto_lib_desc.convert_pk != NULL) {
return crypto_lib_desc.convert_pk(full_pk_ptr, full_pk_len,
hashed_pk_ptr, hashed_pk_len);
}
*hashed_pk_ptr = full_pk_ptr;
*hashed_pk_len = full_pk_len;
return 0;
}
/*
* Authenticated decryption of data
*

View File

@ -330,5 +330,5 @@ static int verify_hash(void *data_ptr, unsigned int data_len,
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, NULL, NULL);

View File

@ -302,4 +302,4 @@ static int verify_hash(void *data_ptr, unsigned int data_len,
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, NULL, NULL);

View File

@ -396,18 +396,19 @@ static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
#if TF_MBEDTLS_USE_AES_GCM
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
auth_decrypt);
auth_decrypt, NULL);
#else
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
NULL);
NULL, NULL);
#endif
#elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
#if TF_MBEDTLS_USE_AES_GCM
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash,
auth_decrypt);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
auth_decrypt, NULL);
#else
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
NULL, NULL);
#endif
#elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash);
REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL);
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */

View File

@ -120,4 +120,4 @@ static int verify_hash(void *data_ptr, unsigned int data_len,
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL, NULL, NULL);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -52,8 +52,6 @@ typedef struct crypto_lib_desc_s {
/* Verify a digital signature. Return one of the
* 'enum crypto_ret_value' options */
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
int (*verify_signature)(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
@ -62,17 +60,15 @@ CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/* Verify a hash. Return one of the 'enum crypto_ret_value' options */
int (*verify_hash)(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/* Calculate a hash. Return hash value */
int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE]);
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
/* Convert Public key (optional) */
int (*convert_pk)(void *full_pk_ptr, unsigned int full_pk_len,
void **hashed_pk_ptr, unsigned int *hashed_pk_len);
/*
* Authenticated decryption. Return one of the
@ -94,16 +90,16 @@ static inline void crypto_mod_init(void)
}
#endif /* CRYPTO_SUPPORT */
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
#if (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY) || \
(CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC)
int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg_ptr, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len);
int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#endif /* (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY) || \
(CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC) */
int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
@ -111,44 +107,29 @@ int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
unsigned int iv_len, const void *tag,
unsigned int tag_len);
#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
#if (CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY) || \
(CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC)
int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE]);
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#endif /* (CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY) || \
(CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC) */
int crypto_mod_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
void **hashed_pk_ptr, unsigned int *hashed_pk_len);
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/* Macro to register a cryptographic library */
#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
_calc_hash, _auth_decrypt) \
_calc_hash, _auth_decrypt, _convert_pk) \
const crypto_lib_desc_t crypto_lib_desc = { \
.name = _name, \
.init = _init, \
.verify_signature = _verify_signature, \
.verify_hash = _verify_hash, \
.calc_hash = _calc_hash, \
.auth_decrypt = _auth_decrypt \
.auth_decrypt = _auth_decrypt, \
.convert_pk = _convert_pk \
}
#elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
_auth_decrypt) \
const crypto_lib_desc_t crypto_lib_desc = { \
.name = _name, \
.init = _init, \
.verify_signature = _verify_signature, \
.verify_hash = _verify_hash, \
.auth_decrypt = _auth_decrypt \
}
#elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
#define REGISTER_CRYPTO_LIB(_name, _init, _calc_hash) \
const crypto_lib_desc_t crypto_lib_desc = { \
.name = _name, \
.init = _init, \
.calc_hash = _calc_hash, \
}
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
extern const crypto_lib_desc_t crypto_lib_desc;

View File

@ -44,10 +44,17 @@ enum fw_enc_status_t;
* plat_get_rotpk_info() flags
******************************************************************************/
#define ROTPK_IS_HASH (1 << 0)
/* Flag used to skip verification of the certificate ROTPK while the platform
ROTPK is not deployed */
#define ROTPK_NOT_DEPLOYED (1 << 1)
static inline bool is_rotpk_flags_valid(unsigned int flags)
{
unsigned int valid_flags = ROTPK_IS_HASH;
return (flags == ROTPK_NOT_DEPLOYED) || ((flags & ~valid_flags) == 0);
}
/*******************************************************************************
* plat_get_enc_key_info() flags
******************************************************************************/
@ -345,8 +352,6 @@ 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) 2022, STMicroelectronics - All Rights Reserved
* Copyright (c) 2022-2023, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -167,7 +167,7 @@ uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
return ret;
}
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
static int crypto_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);
@ -220,7 +220,7 @@ static uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
return 0;
}
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
static int crypto_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)];
@ -650,13 +650,16 @@ REGISTER_CRYPTO_LIB("stm32_crypto_lib",
crypto_lib_init,
crypto_verify_signature,
crypto_verify_hash,
crypto_auth_decrypt);
NULL,
crypto_auth_decrypt,
crypto_convert_pk);
#else /* No decryption support */
REGISTER_CRYPTO_LIB("stm32_crypto_lib",
crypto_lib_init,
crypto_verify_signature,
crypto_verify_hash,
NULL);
NULL,
NULL,
crypto_convert_pk);
#endif