Merge pull request #8041 from mpg/tfm-p256m

Test TF-M config with p256-m driver
This commit is contained in:
Manuel Pégourié-Gonnard 2023-09-20 16:09:56 +00:00 committed by GitHub
commit 5edb942708
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 537 additions and 95 deletions

View File

@ -1466,4 +1466,49 @@ int p256_ecdsa_verify(const uint8_t sig[64], const uint8_t pub[64],
return P256_INVALID_SIGNATURE;
}
/**********************************************************************
*
* Key management utilities
*
**********************************************************************/
int p256_validate_pubkey(const uint8_t pub[64])
{
uint32_t x[8], y[8];
int ret = point_from_bytes(x, y, pub);
return ret == 0 ? P256_SUCCESS : P256_INVALID_PUBKEY;
}
int p256_validate_privkey(const uint8_t priv[32])
{
uint32_t s[8];
int ret = scalar_from_bytes(s, priv);
zeroize(s, sizeof(s));
return ret == 0 ? P256_SUCCESS : P256_INVALID_PRIVKEY;
}
int p256_public_from_private(uint8_t pub[64], const uint8_t priv[32])
{
int ret;
uint32_t s[8];
ret = scalar_from_bytes(s, priv);
if (ret != 0)
return P256_INVALID_PRIVKEY;
/* compute and ouput the associated public key */
uint32_t x[8], y[8];
scalar_mult(x, y, p256_gx, p256_gy, s);
/* the associated public key is not a secret, the scalar was */
CT_UNPOISON(x, 32);
CT_UNPOISON(y, 32);
zeroize(s, sizeof(s));
point_to_bytes(pub, x, y);
return P256_SUCCESS;
}
#endif

View File

@ -89,6 +89,45 @@ int p256_ecdsa_sign(uint8_t sig[64], const uint8_t priv[32],
int p256_ecdsa_verify(const uint8_t sig[64], const uint8_t pub[64],
const uint8_t *hash, size_t hlen);
/*
* Public key validation
*
* Note: you never need to call this function, as all other functions always
* validate their input; however it's availabe if you want to validate the key
* without performing an operation.
*
* [in] pub: the public key, as two big-endian integers
*
* return: P256_SUCCESS if the key is valid
* P256_INVALID_PUBKEY if pub is invalid
*/
int p256_validate_pubkey(const uint8_t pub[64]);
/*
* Private key validation
*
* Note: you never need to call this function, as all other functions always
* validate their input; however it's availabe if you want to validate the key
* without performing an operation.
*
* [in] priv: the private key, as a big-endian integer
*
* return: P256_SUCCESS if the key is valid
* P256_INVALID_PRIVKEY if priv is invalid
*/
int p256_validate_privkey(const uint8_t priv[32]);
/*
* Compute public key from private key
*
* [out] pub: the associated public key, as two big-endian integers
* [in] priv: the private key, as a big-endian integer
*
* return: P256_SUCCESS on success
* P256_INVALID_PRIVKEY if priv is invalid
*/
int p256_public_from_private(uint8_t pub[64], const uint8_t priv[32]);
#ifdef __cplusplus
}
#endif

View File

@ -24,6 +24,7 @@
#include "psa/crypto.h"
#include "psa_crypto_driver_wrappers.h"
#include <stddef.h>
#include <string.h>
#if defined(MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED)
@ -37,10 +38,20 @@
* total of 65 bytes.
*
* p256-m's internal format for private keys matches PSA. Its format for public
* keys is only 64 bytes; the same as PSA but without the leading byte (0x04).
* keys is only 64 bytes: the same as PSA but without the leading byte (0x04).
* Hence, when passing public keys from PSA to p256-m, the leading byte is
* removed.
*
* Shared secret and signature have the same format between PSA and p256-m.
*/
#define PSA_PUBKEY_SIZE 65
#define PSA_PUBKEY_HEADER_BYTE 0x04
#define P256_PUBKEY_SIZE 64
#define PRIVKEY_SIZE 32
#define SHARED_SECRET_SIZE 32
#define SIGNATURE_SIZE 64
#define CURVE_BITS 256
/* Convert between p256-m and PSA error codes */
static psa_status_t p256_to_psa_error(int ret)
@ -59,6 +70,83 @@ static psa_status_t p256_to_psa_error(int ret)
}
}
psa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits)
{
/* Check the key size */
if (*bits != 0 && *bits != CURVE_BITS) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* Validate the key (and its type and size) */
psa_key_type_t type = psa_get_key_type(attributes);
if (type == PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
if (data_length != PSA_PUBKEY_SIZE) {
return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;
}
/* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
if (p256_validate_pubkey(data + 1) != P256_SUCCESS) {
return PSA_ERROR_INVALID_ARGUMENT;
}
} else if (type == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
if (data_length != PRIVKEY_SIZE) {
return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;
}
if (p256_validate_privkey(data) != P256_SUCCESS) {
return PSA_ERROR_INVALID_ARGUMENT;
}
} else {
return PSA_ERROR_NOT_SUPPORTED;
}
*bits = CURVE_BITS;
/* We only support the export format for input, so just copy. */
if (key_buffer_size < data_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(key_buffer, data, data_length);
*key_buffer_length = data_length;
return PSA_SUCCESS;
}
psa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
/* Is this the right curve? */
size_t bits = psa_get_key_bits(attributes);
psa_key_type_t type = psa_get_key_type(attributes);
if (bits != CURVE_BITS || type != PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* Validate sizes, as p256-m expects fixed-size buffers */
if (key_buffer_size != PRIVKEY_SIZE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data_size < PSA_PUBKEY_SIZE) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
data[0] = PSA_PUBKEY_HEADER_BYTE;
int ret = p256_public_from_private(data + 1, key_buffer);
if (ret == P256_SUCCESS) {
*data_length = PSA_PUBKEY_SIZE;
}
return p256_to_psa_error(ret);
}
psa_status_t p256_transparent_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer,
@ -69,13 +157,9 @@ psa_status_t p256_transparent_generate_key(
* of driver entry-points. (void) used to avoid compiler warning. */
(void) attributes;
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
/*
* p256-m generates a 32 byte private key, and expects to write to a buffer
* that is of that size. */
if (key_buffer_size != 32) {
return status;
/* Validate sizes, as p256-m expects fixed-size buffers */
if (key_buffer_size != PRIVKEY_SIZE) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/*
@ -83,15 +167,14 @@ psa_status_t p256_transparent_generate_key(
* keys. Allocate a buffer to which the public key will be written. The
* private key will be written to key_buffer, which is passed to this
* function as an argument. */
uint8_t public_key_buffer[64];
uint8_t public_key_buffer[P256_PUBKEY_SIZE];
status = p256_to_psa_error(
p256_gen_keypair(key_buffer, public_key_buffer));
if (status == PSA_SUCCESS) {
*key_buffer_length = 32;
int ret = p256_gen_keypair(key_buffer, public_key_buffer);
if (ret == P256_SUCCESS) {
*key_buffer_length = PRIVKEY_SIZE;
}
return status;
return p256_to_psa_error(ret);
}
psa_status_t p256_transparent_key_agreement(
@ -111,25 +194,22 @@ psa_status_t p256_transparent_key_agreement(
(void) attributes;
(void) alg;
/*
* Check that private key = 32 bytes, peer public key = 65 bytes,
* and that the shared secret buffer is big enough. */
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
if (key_buffer_size != 32 || shared_secret_size < 32 ||
peer_key_length != 65) {
return status;
/* Validate sizes, as p256-m expects fixed-size buffers */
if (key_buffer_size != PRIVKEY_SIZE || peer_key_length != PSA_PUBKEY_SIZE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (shared_secret_size < SHARED_SECRET_SIZE) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/* We add 1 to peer_key pointer to omit the leading byte of the public key
* representation (0x04). See information about PSA key formats at the top
* of the file. */
status = p256_to_psa_error(
p256_ecdh_shared_secret(shared_secret, key_buffer, peer_key+1));
if (status == PSA_SUCCESS) {
*shared_secret_length = 32;
/* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
const uint8_t *peer_key_p256m = peer_key + 1;
int ret = p256_ecdh_shared_secret(shared_secret, key_buffer, peer_key_p256m);
if (ret == P256_SUCCESS) {
*shared_secret_length = SHARED_SECRET_SIZE;
}
return status;
return p256_to_psa_error(ret);
}
psa_status_t p256_transparent_sign_hash(
@ -149,21 +229,23 @@ psa_status_t p256_transparent_sign_hash(
(void) attributes;
(void) alg;
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
if (key_buffer_size != 32 || signature_size != 64) {
return status;
/* Validate sizes, as p256-m expects fixed-size buffers */
if (key_buffer_size != PRIVKEY_SIZE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (signature_size < SIGNATURE_SIZE) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = p256_to_psa_error(
p256_ecdsa_sign(signature, key_buffer, hash, hash_length));
if (status == PSA_SUCCESS) {
*signature_length = 64;
int ret = p256_ecdsa_sign(signature, key_buffer, hash, hash_length);
if (ret == P256_SUCCESS) {
*signature_length = SIGNATURE_SIZE;
}
return status;
return p256_to_psa_error(ret);
}
/* This function expects the key buffer to contain a 65 byte public key,
/* This function expects the key buffer to contain a PSA public key,
* as exported by psa_export_public_key() */
static psa_status_t p256_verify_hash_with_public_key(
const uint8_t *key_buffer,
@ -173,19 +255,19 @@ static psa_status_t p256_verify_hash_with_public_key(
const uint8_t *signature,
size_t signature_length)
{
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
if (key_buffer_size != 65 || signature_length != 64 || *key_buffer != 0x04) {
return status;
/* Validate sizes, as p256-m expects fixed-size buffers */
if (key_buffer_size != PSA_PUBKEY_SIZE || *key_buffer != PSA_PUBKEY_HEADER_BYTE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (signature_length != SIGNATURE_SIZE) {
return PSA_ERROR_INVALID_SIGNATURE;
}
/* We add 1 to public_key_buffer pointer to omit the leading byte of the
* public key representation (0x04). See information about PSA key formats
* at the top of the file. */
const uint8_t *public_key_buffer = key_buffer + 1;
status = p256_to_psa_error(
p256_ecdsa_verify(signature, public_key_buffer, hash, hash_length));
/* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
const uint8_t *public_key_p256m = key_buffer + 1;
int ret = p256_ecdsa_verify(signature, public_key_p256m, hash, hash_length);
return status;
return p256_to_psa_error(ret);
}
psa_status_t p256_transparent_verify_hash(
@ -203,10 +285,10 @@ psa_status_t p256_transparent_verify_hash(
(void) alg;
psa_status_t status;
uint8_t public_key_buffer[65];
size_t public_key_buffer_size = 65;
uint8_t public_key_buffer[PSA_PUBKEY_SIZE];
size_t public_key_buffer_size = PSA_PUBKEY_SIZE;
size_t public_key_length = 65;
size_t public_key_length = PSA_PUBKEY_SIZE;
/* As p256-m doesn't require dynamic allocation, we want to avoid it in
* the entrypoint functions as well. psa_driver_wrapper_export_public_key()
* requires size_t*, so we use a pointer to a stack variable. */

View File

@ -29,6 +29,66 @@
#include "psa/crypto_types.h"
/** Import SECP256R1 key.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] data The raw key material. For private keys
* this must be a big-endian integer of 32
* bytes; for public key this must be an
* uncompressed ECPoint (65 bytes).
* \param[in] data_length The size of the raw key material.
* \param[out] key_buffer The buffer to contain the key data in
* output format upon successful return.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] key_buffer_length The length of the data written in \p
* key_buffer in bytes.
* \param[out] bits The bitsize of the key.
*
* \retval #PSA_SUCCESS
* Success. Keypair generated and stored in buffer.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The input is not supported by this driver (not SECP256R1).
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The input is invalid.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p key_buffer_size is too small.
*/
psa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits);
/** Export SECP256R1 public key, from the private key.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The private key in the export format.
* \param[in] key_buffer_size The size of the private key in bytes.
* \param[out] data The buffer to contain the public key in
* the export format upon successful return.
* \param[in] data_size The size of the \p data buffer in bytes.
* \param[out] data_length The length written to \p data in bytes.
*
* \retval #PSA_SUCCESS
* Success. Keypair generated and stored in buffer.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The input is not supported by this driver (not SECP256R1).
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The input is invalid.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p key_buffer_size is too small.
*/
psa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *data,
size_t data_size,
size_t *data_length);
/** Generate SECP256R1 ECC Key Pair.
* Interface function which calls the p256-m key generation function and
* places it in the key buffer provided by the caller (Mbed TLS) in the
@ -44,9 +104,10 @@
*
* \retval #PSA_SUCCESS
* Success. Keypair generated and stored in buffer.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_GENERIC_ERROR
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p key_buffer_size is too small.
* \retval #PSA_ERROR_GENERIC_ERROR
* The internal RNG failed.
*/
psa_status_t p256_transparent_generate_key(
const psa_key_attributes_t *attributes,
@ -72,9 +133,12 @@ psa_status_t p256_transparent_generate_key(
* bytes.
* \param[out] shared_secret_length On success, the number of bytes that
* make up the returned shared secret.
* \retval #PSA_SUCCESS
* Success. Shared secret successfully calculated.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_SUCCESS
* Success. Shared secret successfully calculated.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The input is invalid.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p shared_secret_size is too small.
*/
psa_status_t p256_transparent_key_agreement(
const psa_key_attributes_t *attributes,
@ -103,10 +167,14 @@ psa_status_t p256_transparent_key_agreement(
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS
* \retval #PSA_SUCCESS
* Success. Hash was signed successfully.
* respectively of the key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The input is invalid.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p signature_size is too small.
* \retval #PSA_ERROR_GENERIC_ERROR
* The internal RNG failed.
*/
psa_status_t p256_transparent_sign_hash(
const psa_key_attributes_t *attributes,
@ -142,12 +210,13 @@ psa_status_t p256_transparent_sign_hash(
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The input is invalid.
*/
psa_status_t p256_transparent_verify_hash(
const psa_key_attributes_t *attributes,

View File

@ -173,11 +173,11 @@ typedef struct mbedtls_pk_rsassa_pss_options {
/* Internal helper to define which fields in the pk_context structure below
* should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly)
* format. It should be noticed that this only affects how data is stored, not
* format. It should be noted that this only affects how data is stored, not
* which functions are used for various operations. The overall picture looks
* like this:
* - if USE_PSA is not defined and ECP_C is then use ecp_keypair data structure
* and legacy functions
* - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data
* structure and legacy functions
* - if USE_PSA is defined and
* - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly
* format and use PSA functions
@ -185,13 +185,13 @@ typedef struct mbedtls_pk_rsassa_pss_options {
*
* The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long
* as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the
* ecp_keypair structure inside the pk_context so he/she can modify it using
* ecp_keypair structure inside the pk_context so they can modify it using
* ECP functions which are not under PK module's control.
*/
#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
!defined(MBEDTLS_ECP_C)
#define MBEDTLS_PK_USE_PSA_EC_DATA
#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_ECP_C */
#endif
/* Helper symbol to state that the PK module has support for EC keys. This
* can either be provided through the legacy ECP solution or through the
@ -200,28 +200,6 @@ typedef struct mbedtls_pk_rsassa_pss_options {
#define MBEDTLS_PK_HAVE_ECC_KEYS
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
/* Internal helper to define which fields in the pk_context structure below
* should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly)
* format. It should be noted that this only affect how data is stored, not
* which functions are used for various operations. The overall picture looks
* like this:
* - if USE_PSA is not defined and ECP_C is then use ecp_keypair data structure
* and legacy functions
* - if USE_PSA is defined and
* - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly
* format and use PSA functions
* - if !ECP_C then use new raw data and PSA functions directly.
*
* The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long
* as ECP_C is defined mbedtls_pk_ec() gives the user read/write access to the
* ecp_keypair structure inside the pk_context so they can modify it using
* ECP functions which are not under the PK module's control.
*/
#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
!defined(MBEDTLS_ECP_C)
#define MBEDTLS_PK_USE_PSA_EC_DATA
#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_ECP_C */
/**
* \brief Types for interfacing with the debug module
*/

View File

@ -1 +1 @@
["mbedtls_test_opaque_driver.json","mbedtls_test_transparent_driver.json"]
["mbedtls_test_opaque_driver.json","mbedtls_test_transparent_driver.json","p256_transparent_driver.json"]

View File

@ -0,0 +1,20 @@
{
"prefix": "p256",
"type": "transparent",
"mbedtls/h_condition": "defined(MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED)",
"headers": ["../3rdparty/p256-m/p256-m_driver_entrypoints.h"],
"capabilities": [
{
"mbedtls/c_condition": "defined(MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED)",
"_comment_entry_points": "This is not the complete list of entry points supported by this driver, only those that are currently supported in JSON. See docs/psa-driver-example-and-guide.md",
"entry_points": ["import_key", "export_public_key"],
"algorithms": ["PSA_ALG_ECDH", "PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)"],
"key_types": [
"PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)",
"PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)"
],
"key_sizes": [256],
"fallback": false
}
]
}

View File

@ -2884,6 +2884,105 @@ component_test_psa_crypto_config_reference_ecc_ffdh_no_bignum () {
common_test_psa_crypto_config_reference_ecc_ffdh_no_bignum "ECC_DH"
}
# Helper for setting common configurations between:
# - component_test_tfm_config_p256m_driver_accel_ec()
# - component_test_tfm_config()
common_tfm_config () {
# Enable TF-M config
cp configs/tfm_mbedcrypto_config_profile_medium.h "$CONFIG_H"
cp configs/crypto_config_profile_medium.h "$CRYPTO_CONFIG_H"
# Adjust for the fact that we're building outside the TF-M environment.
#
# TF-M has separation, our build doesn't
scripts/config.py unset MBEDTLS_PSA_CRYPTO_SPM
scripts/config.py unset MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
# TF-M provdes its own (dummy) implemenation, from their tree
scripts/config.py unset MBEDTLS_AES_DECRYPT_ALT
scripts/config.py unset MBEDTLS_AES_SETKEY_DEC_ALT
# We have an OS that provides entropy, use it
scripts/config.py unset MBEDTLS_NO_PLATFORM_ENTROPY
# Other config adjustments to make the tests pass.
# Those should probably be adopted upstream.
#
# - USE_PSA_CRYPTO for PK_HAVE_ECC_KEYS
echo "#define MBEDTLS_USE_PSA_CRYPTO" >> "$CONFIG_H"
# pkparse.c and pkwrite.c fail to link without this
echo "#define MBEDTLS_OID_C" >> "$CONFIG_H"
# - ASN1_[PARSE/WRITE]_C found by check_config.h for pkparse/pkwrite
echo "#define MBEDTLS_ASN1_PARSE_C" >> "$CONFIG_H"
echo "#define MBEDTLS_ASN1_WRITE_C" >> "$CONFIG_H"
# - MD_C for HKDF_C
echo "#define MBEDTLS_MD_C" >> "$CONFIG_H"
# Config adjustments for better test coverage in our environment.
# These are not needed just to build and pass tests.
#
# Enable filesystem I/O for the benefit of PK parse/write tests.
echo "#define MBEDTLS_FS_IO" >> "$CONFIG_H"
# Disable this for maximal ASan efficiency
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
# Config adjustments for features that are not supported
# when using only drivers / by p256-m
#
# Disable all the features that auto-enable ECP_LIGHT (see build_info.h)
scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE
# Disable deterministic ECDSA as p256-m only does randomized
scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_DETERMINISTIC_ECDSA
}
# Keep this in sync with component_test_tfm_config() as they are both meant
# to be used in analyze_outcomes.py for driver's coverage analysis.
component_test_tfm_config_p256m_driver_accel_ec () {
msg "build: TF-M config + p256m driver + accel ECDH(E)/ECDSA"
common_tfm_config
# Set the list of accelerated components in order to remove them from
# builtin support.
loc_accel_list="ALG_ECDSA \
ALG_ECDH \
KEY_TYPE_ECC_KEY_PAIR_BASIC \
KEY_TYPE_ECC_KEY_PAIR_IMPORT \
KEY_TYPE_ECC_KEY_PAIR_EXPORT \
KEY_TYPE_ECC_KEY_PAIR_GENERATE \
KEY_TYPE_ECC_PUBLIC_KEY"
loc_accel_flags="$( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
# Build crypto library specifying we want to use P256M code for EC operations
make CFLAGS="$ASAN_CFLAGS $loc_accel_flags -DMBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED" LDFLAGS="$ASAN_CFLAGS"
# Make sure any built-in EC alg was not re-enabled by accident (additive config)
not grep mbedtls_ecdsa_ library/ecdsa.o
not grep mbedtls_ecdh_ library/ecdh.o
not grep mbedtls_ecjpake_ library/ecjpake.o
# Also ensure that ECP, RSA, DHM or BIGNUM modules were not re-enabled
not grep mbedtls_ecp_ library/ecp.o
not grep mbedtls_rsa_ library/rsa.o
not grep mbedtls_dhm_ library/dhm.o
not grep mbedtls_mpi_ library/bignum.o
# Run the tests
msg "test: TF-M config + p256m driver + accel ECDH(E)/ECDSA"
make test
}
# Keep this in sync with component_test_tfm_config_p256m_driver_accel_ec() as
# they are both meant to be used in analyze_outcomes.py for driver's coverage
# analysis.
component_test_tfm_config() {
common_tfm_config
msg "build: TF-M config"
make tests
msg "test: TF-M config"
make test
}
# Helper function used in:
# - component_test_psa_crypto_config_accel_all_curves_except_p192
# - component_test_psa_crypto_config_accel_all_curves_except_x25519

View File

@ -521,6 +521,102 @@ TASKS = {
'ignored_tests': {}
}
},
'analyze_driver_vs_reference_tfm_config': {
'test_function': do_analyze_driver_vs_reference,
'args': {
'component_ref': 'test_tfm_config',
'component_driver': 'test_tfm_config_p256m_driver_accel_ec',
'ignored_suites': [
# Ignore test suites for the modules that are disabled in the
# accelerated test case.
'ecp',
'ecdsa',
'ecdh',
'ecjpake',
'bignum_core',
'bignum_random',
'bignum_mod',
'bignum_mod_raw',
'bignum.generated',
'bignum.misc',
],
'ignored_tests': {
# Ignore all tests that require DERIVE support which is disabled
# in the driver version
'test_suite_psa_crypto': [
'PSA key agreement setup: ECDH + HKDF-SHA-256: good',
('PSA key agreement setup: ECDH + HKDF-SHA-256: good, key algorithm broader '
'than required'),
'PSA key agreement setup: ECDH + HKDF-SHA-256: public key not on curve',
'PSA key agreement setup: KDF instead of a key agreement algorithm',
'PSA key agreement setup: bad key agreement algorithm',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: capacity=8160',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 0+32',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 1+31',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 31+1',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 32+0',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 32+32',
'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 64+0',
'PSA key derivation: ECDH on P256 with HKDF-SHA256, info first',
'PSA key derivation: ECDH on P256 with HKDF-SHA256, key output',
'PSA key derivation: ECDH on P256 with HKDF-SHA256, missing info',
'PSA key derivation: ECDH on P256 with HKDF-SHA256, omitted salt',
'PSA key derivation: ECDH on P256 with HKDF-SHA256, raw output',
'PSA key derivation: ECDH on P256 with HKDF-SHA256, salt after secret',
'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, good case',
'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, missing label',
'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, missing label and secret',
'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, no inputs',
'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, SHA-256, 0+48, ka',
'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, SHA-256, 24+24, ka',
'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, SHA-256, 48+0, ka',
'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, bad state #1, ka',
'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, bad state #3, ka',
'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, bad state #4, ka',
'PSA key derivation: bits=7 invalid for ECC BRAINPOOL_P_R1 (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC MONTGOMERY (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC SECP_K1 (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC SECP_R1 (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC SECP_R2 (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC SECT_K1 (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC SECT_R1 (ECC enabled)',
'PSA key derivation: bits=7 invalid for ECC SECT_R2 (ECC enabled)',
'PSA raw key agreement: ECDH SECP256R1 (RFC 5903)',
],
'test_suite_random': [
'PSA classic wrapper: ECDSA signature (SECP256R1)',
],
'test_suite_psa_crypto_pake': [
'PSA PAKE: ecjpake size macros',
],
'test_suite_asn1parse': [
# This test depends on BIGNUM_C
'INTEGER too large for mpi',
],
'test_suite_asn1write': [
# Following tests depends on BIGNUM_C
'ASN.1 Write mpi 0 (1 limb)',
'ASN.1 Write mpi 0 (null)',
'ASN.1 Write mpi 0x100',
'ASN.1 Write mpi 0x7f',
'ASN.1 Write mpi 0x7f with leading 0 limb',
'ASN.1 Write mpi 0x80',
'ASN.1 Write mpi 0x80 with leading 0 limb',
'ASN.1 Write mpi 0xff',
'ASN.1 Write mpi 1',
'ASN.1 Write mpi, 127*8 bits',
'ASN.1 Write mpi, 127*8+1 bits',
'ASN.1 Write mpi, 127*8-1 bits',
'ASN.1 Write mpi, 255*8 bits',
'ASN.1 Write mpi, 255*8-1 bits',
'ASN.1 Write mpi, 256*8-1 bits',
],
}
}
}
}
def main():

View File

@ -1366,7 +1366,21 @@ void import_with_data(data_t *data, int type_arg,
psa_set_key_bits(&attributes, attr_bits);
status = psa_import_key(&attributes, data->x, data->len, &key);
TEST_EQUAL(status, expected_status);
/* When expecting INVALID_ARGUMENT, also accept NOT_SUPPORTED.
*
* This can happen with a type supported only by a driver:
* - the driver sees the invalid data (for example wrong size) and thinks
* "well perhaps this is a key size I don't support" so it returns
* NOT_SUPPORTED which is correct at this point;
* - we fallback to built-ins, which don't support this type, so return
* NOT_SUPPORTED which again is correct at this point.
*/
if (expected_status == PSA_ERROR_INVALID_ARGUMENT &&
status == PSA_ERROR_NOT_SUPPORTED) {
; // OK
} else {
TEST_EQUAL(status, expected_status);
}
if (status != PSA_SUCCESS) {
goto exit;
}