1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge pull request #6426 from aditya-deshpande-arm/driver-wrapper-key-agreement

Add driver dispatch layer for raw key agreement, along with test call for transparent drivers.
This commit is contained in:
Paul Elliott
2022-12-01 11:40:52 +00:00
committed by GitHub
15 changed files with 678 additions and 98 deletions

View File

@ -5723,63 +5723,46 @@ psa_status_t psa_key_derivation_input_key(
/* Key agreement */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
psa_status_t psa_key_agreement_raw_builtin( const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
const mbedtls_ecp_keypair *our_key,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length )
{
mbedtls_ecp_keypair *their_key = NULL;
mbedtls_ecdh_context ecdh;
psa_status_t status;
size_t bits = 0;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits );
mbedtls_ecdh_init( &ecdh );
status = mbedtls_psa_ecp_load_representation(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
bits,
peer_key,
peer_key_length,
&their_key );
if( status != PSA_SUCCESS )
goto exit;
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
if( status != PSA_SUCCESS )
goto exit;
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) );
if( status != PSA_SUCCESS )
goto exit;
status = mbedtls_to_psa_error(
mbedtls_ecdh_calc_secret( &ecdh,
shared_secret_length,
shared_secret, shared_secret_size,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE ) );
if( status != PSA_SUCCESS )
goto exit;
if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
status = PSA_ERROR_CORRUPTION_DETECTED;
exit:
if( status != PSA_SUCCESS )
mbedtls_platform_zeroize( shared_secret, shared_secret_size );
mbedtls_ecdh_free( &ecdh );
mbedtls_ecp_keypair_free( their_key );
mbedtls_free( their_key );
return( status );
}
switch( alg )
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
case PSA_ALG_ECDH:
return( mbedtls_psa_key_agreement_ecdh( attributes, key_buffer,
key_buffer_size, alg,
peer_key, peer_key_length,
shared_secret,
shared_secret_size,
shared_secret_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
default:
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) peer_key;
(void) peer_key_length;
(void) shared_secret;
(void) shared_secret_size;
(void) shared_secret_length;
return( PSA_ERROR_NOT_SUPPORTED );
}
}
#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES
/** Internal function for raw key agreement
* Calls the driver wrapper which will hand off key agreement task
* to the driver's implementation if a driver is present.
* Fallback specified in the driver wrapper is built-in raw key agreement
* (psa_key_agreement_raw_builtin).
*/
static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg,
psa_key_slot_t *private_key,
const uint8_t *peer_key,
@ -5788,38 +5771,20 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg,
size_t shared_secret_size,
size_t *shared_secret_length )
{
switch( alg )
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
case PSA_ALG_ECDH:
if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) )
return( PSA_ERROR_INVALID_ARGUMENT );
mbedtls_ecp_keypair *ecp = NULL;
psa_status_t status = mbedtls_psa_ecp_load_representation(
private_key->attr.type,
private_key->attr.bits,
private_key->key.data,
private_key->key.bytes,
&ecp );
if( status != PSA_SUCCESS )
return( status );
status = psa_key_agreement_ecdh( peer_key, peer_key_length,
ecp,
shared_secret, shared_secret_size,
shared_secret_length );
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
return( status );
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
default:
(void) private_key;
(void) peer_key;
(void) peer_key_length;
(void) shared_secret;
(void) shared_secret_size;
(void) shared_secret_length;
return( PSA_ERROR_NOT_SUPPORTED );
}
if( !PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
return( PSA_ERROR_NOT_SUPPORTED );
psa_key_attributes_t attributes = {
.core = private_key->attr
};
return( psa_driver_wrapper_key_agreement( &attributes,
private_key->key.data,
private_key->key.bytes, alg,
peer_key, peer_key_length,
shared_secret,
shared_secret_size,
shared_secret_length ) );
}
/* Note that if this function fails, you must call psa_key_derivation_abort()
@ -5832,7 +5797,7 @@ static psa_status_t psa_key_agreement_internal( psa_key_derivation_operation_t *
size_t peer_key_length )
{
psa_status_t status;
uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE];
uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE];
size_t shared_secret_length = 0;
psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE( operation->alg );

View File

@ -549,4 +549,62 @@ psa_status_t psa_verify_hash_builtin(
*/
psa_status_t psa_validate_unstructured_key_bit_size( psa_key_type_t type,
size_t bits );
/** Perform a key agreement and return the raw shared secret, using
built-in raw key agreement functions.
*
* \note The signature of this function is that of a PSA driver
* key_agreement entry point. This function behaves as a key_agreement
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the private key
* context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in
* bytes.
* \param[in] alg A key agreement algorithm that is
* compatible with the type of the key.
* \param[in] peer_key The buffer containing the key context
* of the peer's public key.
* \param[in] peer_key_length Size of the \p peer_key buffer in
* bytes.
* \param[out] shared_secret The buffer to which the shared secret
* is to be written.
* \param[in] shared_secret_size Size of the \p shared_secret buffer in
* 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_INVALID_HANDLE
* \retval #PSA_ERROR_NOT_PERMITTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p alg is not a key agreement algorithm, or
* \p private_key is not compatible with \p alg,
* or \p peer_key is not valid for \p alg or not compatible with
* \p private_key.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p shared_secret_size is too small
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not a supported key agreement algorithm.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_BAD_STATE
*/
psa_status_t psa_key_agreement_raw_builtin(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length );
#endif /* PSA_CRYPTO_CORE_H */

View File

@ -357,6 +357,20 @@ psa_status_t psa_driver_wrapper_asymmetric_decrypt(
size_t output_size,
size_t *output_length );
/*
* Raw Key Agreement
*/
psa_status_t psa_driver_wrapper_key_agreement(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length );
#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
/* End of automatically generated file. */

View File

@ -33,6 +33,7 @@
#include "mbedtls/platform.h"
#include <mbedtls/ecdsa.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecp.h>
#include <mbedtls/error.h>
@ -464,4 +465,76 @@ cleanup:
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
/****************************************************************/
/* ECDH Key Agreement */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
psa_status_t mbedtls_psa_key_agreement_ecdh(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
uint8_t *shared_secret, size_t shared_secret_size,
size_t *shared_secret_length )
{
psa_status_t status;
if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( attributes->core.type ) ||
! PSA_ALG_IS_ECDH(alg) )
return( PSA_ERROR_INVALID_ARGUMENT );
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
attributes->core.type,
attributes->core.bits,
key_buffer,
key_buffer_size,
&ecp );
if( status != PSA_SUCCESS )
return( status );
mbedtls_ecp_keypair *their_key = NULL;
mbedtls_ecdh_context ecdh;
size_t bits = 0;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( ecp->grp.id, &bits );
mbedtls_ecdh_init( &ecdh );
status = mbedtls_psa_ecp_load_representation(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
bits,
peer_key,
peer_key_length,
&their_key );
if( status != PSA_SUCCESS )
goto exit;
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
if( status != PSA_SUCCESS )
goto exit;
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params( &ecdh, ecp, MBEDTLS_ECDH_OURS ) );
if( status != PSA_SUCCESS )
goto exit;
status = mbedtls_to_psa_error(
mbedtls_ecdh_calc_secret( &ecdh,
shared_secret_length,
shared_secret, shared_secret_size,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE ) );
if( status != PSA_SUCCESS )
goto exit;
if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
status = PSA_ERROR_CORRUPTION_DETECTED;
exit:
if( status != PSA_SUCCESS )
mbedtls_platform_zeroize( shared_secret, shared_secret_size );
mbedtls_ecdh_free( &ecdh );
mbedtls_ecp_keypair_free( their_key );
mbedtls_free( their_key );
mbedtls_ecp_keypair_free( ecp );
mbedtls_free( ecp );
return( status );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View File

@ -218,4 +218,53 @@ psa_status_t mbedtls_psa_ecdsa_verify_hash(
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
/** Perform a key agreement and return the raw ECDH shared secret.
*
* \note The signature of this function is that of a PSA driver
* key_agreement entry point. This function behaves as a key_agreement
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the private key
* context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in
* bytes.
* \param[in] alg A key agreement algorithm that is
* compatible with the type of the key.
* \param[in] peer_key The buffer containing the key context
* of the peer's public key.
* \param[in] peer_key_length Size of the \p peer_key buffer in
* bytes.
* \param[out] shared_secret The buffer to which the shared secret
* is to be written.
* \param[in] shared_secret_size Size of the \p shared_secret buffer in
* 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_INVALID_HANDLE
* \retval #PSA_ERROR_NOT_PERMITTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p alg is not a key agreement algorithm, or
* \p private_key is not compatible with \p alg,
* or \p peer_key is not valid for \p alg or not compatible with
* \p private_key.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p shared_secret_size is too small
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not a supported key agreement algorithm.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_key_agreement_ecdh(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
uint8_t *shared_secret, size_t shared_secret_size,
size_t *shared_secret_length );
#endif /* PSA_CRYPTO_ECP_H */