Merge pull request #3780 from stevew817/feature/validate_key_in_driver
Add validate_key hooks and tests
This commit is contained in:
commit
a455e71588
@ -739,7 +739,7 @@ static psa_status_t psa_load_ecp_representation( psa_key_type_t type,
|
||||
* - The byte 0x04;
|
||||
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
|
||||
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
|
||||
* So its data length is 2m+1 where n is the key size in bits.
|
||||
* So its data length is 2m+1 where m is the curve size in bits.
|
||||
*/
|
||||
if( ( data_length & 1 ) == 0 )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
@ -969,14 +969,45 @@ static psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot,
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
/** Import key data into a slot. `slot->attr.type` must have been set
|
||||
* previously. This function assumes that the slot does not contain
|
||||
* any key material yet. On failure, the slot content is unchanged. */
|
||||
psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
|
||||
const uint8_t *data,
|
||||
size_t data_length )
|
||||
psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot,
|
||||
const uint8_t* data,
|
||||
size_t data_length )
|
||||
{
|
||||
psa_status_t status = psa_allocate_buffer_to_slot( slot,
|
||||
data_length );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
memcpy( slot->data.key.data, data, data_length );
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
/** Import key data into a slot.
|
||||
*
|
||||
* `slot->type` must have been set previously.
|
||||
* This function assumes that the slot does not contain any key material yet.
|
||||
* On failure, the slot content is unchanged.
|
||||
*
|
||||
* Persistent storage is not affected.
|
||||
*
|
||||
* \param[in,out] slot The key slot to import data into.
|
||||
* Its `type` field must have previously been set to
|
||||
* the desired key type.
|
||||
* It must not contain any key material yet.
|
||||
* \param[in] data Buffer containing the key material to parse and import.
|
||||
* \param data_length Size of \p data in bytes.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
*/
|
||||
static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
|
||||
const uint8_t *data,
|
||||
size_t data_length )
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
size_t bit_size;
|
||||
|
||||
/* zero-length keys are never supported. */
|
||||
if( data_length == 0 )
|
||||
@ -984,7 +1015,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
|
||||
|
||||
if( key_type_is_raw_bytes( slot->attr.type ) )
|
||||
{
|
||||
size_t bit_size = PSA_BYTES_TO_BITS( data_length );
|
||||
bit_size = PSA_BYTES_TO_BITS( data_length );
|
||||
|
||||
/* Ensure that the bytes-to-bits conversion hasn't overflown. */
|
||||
if( data_length > SIZE_MAX / 8 )
|
||||
@ -1000,47 +1031,65 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
|
||||
return( status );
|
||||
|
||||
/* Allocate memory for the key */
|
||||
status = psa_allocate_buffer_to_slot( slot, data_length );
|
||||
status = psa_copy_key_material_into_slot( slot, data, data_length );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
/* copy key into allocated buffer */
|
||||
memcpy( slot->data.key.data, data, data_length );
|
||||
|
||||
/* Write the actual key size to the slot.
|
||||
* psa_start_key_creation() wrote the size declared by the
|
||||
* caller, which may be 0 (meaning unspecified) or wrong. */
|
||||
slot->attr.bits = (psa_key_bits_t) bit_size;
|
||||
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
|
||||
else if( PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
|
||||
{
|
||||
/* Try validation through accelerators first. */
|
||||
bit_size = slot->attr.bits;
|
||||
psa_key_attributes_t attributes = {
|
||||
.core = slot->attr
|
||||
};
|
||||
status = psa_driver_wrapper_validate_key( &attributes,
|
||||
data,
|
||||
data_length,
|
||||
&bit_size );
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
/* Key has been validated successfully by an accelerator.
|
||||
* Copy key material into slot. */
|
||||
status = psa_copy_key_material_into_slot( slot, data, data_length );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
slot->attr.bits = (psa_key_bits_t) bit_size;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
else if( status != PSA_ERROR_NOT_SUPPORTED )
|
||||
return( status );
|
||||
|
||||
/* Key format is not supported by any accelerator, try software fallback
|
||||
* if present. */
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
status = psa_import_ecp_key( slot,
|
||||
data, data_length );
|
||||
#else
|
||||
/* No drivers have been implemented yet, so without mbed TLS backing
|
||||
* there's no way to do ECP with the current library. */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
|
||||
{
|
||||
return( psa_import_ecp_key( slot, data, data_length ) );
|
||||
}
|
||||
#endif /* defined(MBEDTLS_ECP_C) */
|
||||
}
|
||||
else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
|
||||
{
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
status = psa_import_rsa_key( slot,
|
||||
data, data_length );
|
||||
#else
|
||||
/* No drivers have been implemented yet, so without mbed TLS backing
|
||||
* there's no way to do RSA with the current library. */
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
|
||||
{
|
||||
return( psa_import_rsa_key( slot, data, data_length ) );
|
||||
}
|
||||
#endif /* defined(MBEDTLS_RSA_C) */
|
||||
|
||||
/* Fell through the fallback as well, so have nothing else to try. */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown key type */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
/** Calculate the intersection of two algorithm usage policies.
|
||||
@ -1916,22 +1965,11 @@ static psa_status_t psa_finish_key_creation(
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
|
||||
{
|
||||
size_t buffer_size =
|
||||
PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type,
|
||||
slot->attr.bits );
|
||||
uint8_t *buffer = mbedtls_calloc( 1, buffer_size );
|
||||
size_t length = 0;
|
||||
if( buffer == NULL )
|
||||
return( PSA_ERROR_INSUFFICIENT_MEMORY );
|
||||
status = psa_internal_export_key( slot,
|
||||
buffer, buffer_size, &length,
|
||||
0 );
|
||||
if( status == PSA_SUCCESS )
|
||||
status = psa_save_persistent_key( &slot->attr,
|
||||
buffer, length );
|
||||
|
||||
mbedtls_platform_zeroize( buffer, buffer_size );
|
||||
mbedtls_free( buffer );
|
||||
/* Key material is saved in export representation in the slot, so
|
||||
* just pass the slot buffer for storage. */
|
||||
status = psa_save_persistent_key( &slot->attr,
|
||||
slot->data.key.data,
|
||||
slot->data.key.bytes );
|
||||
}
|
||||
}
|
||||
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
|
||||
@ -2179,26 +2217,16 @@ exit:
|
||||
static psa_status_t psa_copy_key_material( const psa_key_slot_t *source,
|
||||
psa_key_slot_t *target )
|
||||
{
|
||||
psa_status_t status;
|
||||
uint8_t *buffer = NULL;
|
||||
size_t buffer_size = 0;
|
||||
size_t length;
|
||||
|
||||
buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type,
|
||||
psa_get_key_slot_bits( source ) );
|
||||
buffer = mbedtls_calloc( 1, buffer_size );
|
||||
if( buffer == NULL )
|
||||
return( PSA_ERROR_INSUFFICIENT_MEMORY );
|
||||
status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 );
|
||||
psa_status_t status = psa_copy_key_material_into_slot( target,
|
||||
source->data.key.data,
|
||||
source->data.key.bytes );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
target->attr.type = source->attr.type;
|
||||
status = psa_import_key_into_slot( target, buffer, length );
|
||||
return( status );
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize( buffer, buffer_size );
|
||||
mbedtls_free( buffer );
|
||||
return( status );
|
||||
target->attr.type = source->attr.type;
|
||||
target->attr.bits = source->attr.bits;
|
||||
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
psa_status_t psa_copy_key( psa_key_handle_t source_handle,
|
||||
|
@ -137,30 +137,26 @@ static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot,
|
||||
*/
|
||||
psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot );
|
||||
|
||||
/** Import key data into a slot.
|
||||
/** Copy key data (in export format) into an empty key slot.
|
||||
*
|
||||
* `slot->type` must have been set previously.
|
||||
* This function assumes that the slot does not contain any key material yet.
|
||||
* On failure, the slot content is unchanged.
|
||||
* This function assumes that the slot does not contain
|
||||
* any key material yet. On failure, the slot content is unchanged.
|
||||
*
|
||||
* Persistent storage is not affected.
|
||||
* \param[in,out] slot Key slot to copy the key into.
|
||||
* \param[in] data Buffer containing the key material.
|
||||
* \param data_length Size of the key buffer.
|
||||
*
|
||||
* \param[in,out] slot The key slot to import data into.
|
||||
* Its `type` field must have previously been set to
|
||||
* the desired key type.
|
||||
* It must not contain any key material yet.
|
||||
* \param[in] data Buffer containing the key material to parse and import.
|
||||
* \param data_length Size of \p data in bytes.
|
||||
*
|
||||
* \retval PSA_SUCCESS
|
||||
* \retval PSA_ERROR_INVALID_ARGUMENT
|
||||
* \retval PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_SUCCESS
|
||||
* The key has been copied successfully.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* Not enough memory was available for allocation of the
|
||||
* copy buffer.
|
||||
* \retval #PSA_ERROR_ALREADY_EXISTS
|
||||
* There was other key material already present in the slot.
|
||||
*/
|
||||
psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
|
||||
const uint8_t *data,
|
||||
size_t data_length );
|
||||
|
||||
psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot,
|
||||
const uint8_t *data,
|
||||
size_t data_length );
|
||||
|
||||
/** Convert an mbed TLS error code to a PSA error code
|
||||
*
|
||||
|
@ -410,6 +410,34 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib
|
||||
#endif /* PSA_CRYPTO_DRIVER_PRESENT */
|
||||
}
|
||||
|
||||
psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
size_t *bits )
|
||||
{
|
||||
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
/* Try accelerators in turn */
|
||||
#if defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
status = test_transparent_validate_key( attributes,
|
||||
data,
|
||||
data_length,
|
||||
bits );
|
||||
/* Declared with fallback == true */
|
||||
if( status != PSA_ERROR_NOT_SUPPORTED )
|
||||
return( status );
|
||||
#endif /* PSA_CRYPTO_DRIVER_TEST */
|
||||
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
|
||||
(void) attributes;
|
||||
(void) data;
|
||||
(void) data_length;
|
||||
(void) bits;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#endif /* PSA_CRYPTO_DRIVER_PRESENT */
|
||||
}
|
||||
|
||||
/*
|
||||
* Cipher functions
|
||||
*/
|
||||
|
@ -43,9 +43,18 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length );
|
||||
|
||||
/*
|
||||
* Key handling functions
|
||||
*/
|
||||
|
||||
psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
|
||||
psa_key_slot_t *slot );
|
||||
|
||||
psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
size_t *bits );
|
||||
|
||||
/*
|
||||
* Cipher functions
|
||||
*/
|
||||
|
@ -141,7 +141,9 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot )
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
|
||||
{
|
||||
status = psa_import_key_into_slot( slot, key_data, key_data_length );
|
||||
status = psa_copy_key_material_into_slot( slot, key_data, key_data_length );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@ -81,9 +81,10 @@ int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key );
|
||||
* This function formats the key data and metadata and saves it to a
|
||||
* persistent storage backend. The storage location corresponding to the
|
||||
* key slot must be empty, otherwise this function will fail. This function
|
||||
* should be called after psa_import_key_into_slot() to ensure the
|
||||
* should be called after loading the key into an internal slot to ensure the
|
||||
* persistent key is not saved into a storage location corresponding to an
|
||||
* already occupied non-persistent key, as well as validating the key data.
|
||||
* already occupied non-persistent key, as well as ensuring the key data is
|
||||
* validated.
|
||||
*
|
||||
*
|
||||
* \param[in] attr The attributes of the key to save.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Test driver for generating keys.
|
||||
* Test driver for generating and verifying keys.
|
||||
*/
|
||||
/* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H
|
||||
#define PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H
|
||||
#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H
|
||||
#define PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
@ -36,18 +36,19 @@ typedef struct {
|
||||
/* If not PSA_SUCCESS, return this error code instead of processing the
|
||||
* function call. */
|
||||
psa_status_t forced_status;
|
||||
/* Count the amount of times one of the keygen driver functions is called. */
|
||||
/* Count the amount of times one of the key management driver functions
|
||||
* is called. */
|
||||
unsigned long hits;
|
||||
} test_driver_keygen_hooks_t;
|
||||
} test_driver_key_management_hooks_t;
|
||||
|
||||
#define TEST_DRIVER_KEYGEN_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
|
||||
static inline test_driver_keygen_hooks_t test_driver_keygen_hooks_init( void )
|
||||
#define TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
|
||||
static inline test_driver_key_management_hooks_t test_driver_key_management_hooks_init( void )
|
||||
{
|
||||
const test_driver_keygen_hooks_t v = TEST_DRIVER_KEYGEN_INIT;
|
||||
const test_driver_key_management_hooks_t v = TEST_DRIVER_KEY_MANAGEMENT_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
extern test_driver_keygen_hooks_t test_driver_keygen_hooks;
|
||||
extern test_driver_key_management_hooks_t test_driver_key_management_hooks;
|
||||
|
||||
psa_status_t test_transparent_generate_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
@ -57,5 +58,10 @@ psa_status_t test_opaque_generate_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *key, size_t key_size, size_t *key_length );
|
||||
|
||||
psa_status_t test_transparent_validate_key(const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
size_t *bits);
|
||||
|
||||
#endif /* PSA_CRYPTO_DRIVER_TEST */
|
||||
#endif /* PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H */
|
||||
#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H */
|
@ -36,7 +36,7 @@ typedef struct {
|
||||
/* If not PSA_SUCCESS, return this error code instead of processing the
|
||||
* function call. */
|
||||
psa_status_t forced_status;
|
||||
/* Count the amount of times one of the keygen driver functions is called. */
|
||||
/* Count the amount of times one of the signature driver functions is called. */
|
||||
unsigned long hits;
|
||||
} test_driver_signature_hooks_t;
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff
|
||||
|
||||
#include "test/drivers/signature.h"
|
||||
#include "test/drivers/keygen.h"
|
||||
#include "test/drivers/key_management.h"
|
||||
#include "test/drivers/cipher.h"
|
||||
#include "test/drivers/size.h"
|
||||
|
||||
|
241
tests/src/drivers/key_management.c
Normal file
241
tests/src/drivers/key_management.c
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Test driver for generating and verifying keys.
|
||||
* Currently only supports generating and verifying ECC keys.
|
||||
*/
|
||||
/* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
#include "test/drivers/key_management.h"
|
||||
|
||||
#include "test/random.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
test_driver_key_management_hooks_t test_driver_key_management_hooks =
|
||||
TEST_DRIVER_KEY_MANAGEMENT_INIT;
|
||||
|
||||
psa_status_t test_transparent_generate_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *key, size_t key_size, size_t *key_length )
|
||||
{
|
||||
++test_driver_key_management_hooks.hits;
|
||||
|
||||
if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_key_management_hooks.forced_status );
|
||||
|
||||
if( test_driver_key_management_hooks.forced_output != NULL )
|
||||
{
|
||||
if( test_driver_key_management_hooks.forced_output_length > key_size )
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
memcpy( key, test_driver_key_management_hooks.forced_output,
|
||||
test_driver_key_management_hooks.forced_output_length );
|
||||
*key_length = test_driver_key_management_hooks.forced_output_length;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
/* Copied from psa_crypto.c */
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
|
||||
&& PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
|
||||
{
|
||||
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
|
||||
psa_get_key_type( attributes ) );
|
||||
mbedtls_ecp_group_id grp_id =
|
||||
mbedtls_ecc_group_of_psa(
|
||||
curve,
|
||||
PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
|
||||
const mbedtls_ecp_curve_info *curve_info =
|
||||
mbedtls_ecp_curve_info_from_grp_id( grp_id );
|
||||
mbedtls_ecp_keypair ecp;
|
||||
mbedtls_test_rnd_pseudo_info rnd_info;
|
||||
memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
if( attributes->domain_parameters_size != 0 )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
if( curve_info->bit_size != psa_get_key_bits( attributes ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
mbedtls_ecp_keypair_init( &ecp );
|
||||
ret = mbedtls_ecp_gen_key( grp_id, &ecp,
|
||||
&mbedtls_test_rnd_pseudo_rand,
|
||||
&rnd_info );
|
||||
if( ret != 0 )
|
||||
{
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( mbedtls_to_psa_error( ret ) );
|
||||
}
|
||||
|
||||
/* Make sure to use export representation */
|
||||
size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) );
|
||||
if( key_size < bytes )
|
||||
{
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
}
|
||||
psa_status_t status = mbedtls_to_psa_error(
|
||||
mbedtls_mpi_write_binary( &ecp.d, key, bytes ) );
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
*key_length = bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( key, 0, bytes );
|
||||
}
|
||||
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( status );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_generate_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *key, size_t key_size, size_t *key_length )
|
||||
{
|
||||
(void) attributes;
|
||||
(void) key;
|
||||
(void) key_size;
|
||||
(void) key_length;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_validate_key(const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
size_t *bits)
|
||||
{
|
||||
++test_driver_key_management_hooks.hits;
|
||||
|
||||
if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_key_management_hooks.forced_status );
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
psa_key_type_t type = psa_get_key_type( attributes );
|
||||
if ( PSA_KEY_TYPE_IS_ECC( type ) )
|
||||
{
|
||||
// Code mostly copied from psa_load_ecp_representation
|
||||
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
mbedtls_ecp_keypair ecp;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if( psa_get_key_bits( attributes ) == 0 )
|
||||
{
|
||||
// Attempt auto-detect of curve bit size
|
||||
size_t curve_size = data_length;
|
||||
|
||||
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) &&
|
||||
PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY )
|
||||
{
|
||||
/* A Weierstrass public key is represented as:
|
||||
* - The byte 0x04;
|
||||
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
|
||||
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
|
||||
* So its data length is 2m+1 where m is the curve size in bits.
|
||||
*/
|
||||
if( ( data_length & 1 ) == 0 )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
curve_size = data_length / 2;
|
||||
|
||||
/* Montgomery public keys are represented in compressed format, meaning
|
||||
* their curve_size is equal to the amount of input. */
|
||||
|
||||
/* Private keys are represented in uncompressed private random integer
|
||||
* format, meaning their curve_size is equal to the amount of input. */
|
||||
}
|
||||
|
||||
grp_id = mbedtls_ecc_group_of_psa( curve, curve_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
grp_id = mbedtls_ecc_group_of_psa( curve,
|
||||
PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
|
||||
}
|
||||
|
||||
const mbedtls_ecp_curve_info *curve_info =
|
||||
mbedtls_ecp_curve_info_from_grp_id( grp_id );
|
||||
|
||||
if( attributes->domain_parameters_size != 0 )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
|
||||
*bits = curve_info->bit_size;
|
||||
|
||||
mbedtls_ecp_keypair_init( &ecp );
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto ecp_exit;
|
||||
|
||||
/* Load the key material. */
|
||||
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
|
||||
{
|
||||
/* Load the public value. */
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
|
||||
data,
|
||||
data_length ) );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto ecp_exit;
|
||||
|
||||
/* Check that the point is on the curve. */
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_check_pubkey( &ecp.grp, &ecp.Q ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load and validate the secret value. */
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_read_key( ecp.grp.id,
|
||||
&ecp,
|
||||
data,
|
||||
data_length ) );
|
||||
}
|
||||
|
||||
ecp_exit:
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( status );
|
||||
}
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#else
|
||||
(void) data;
|
||||
(void) data_length;
|
||||
(void) bits;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Test driver for generating keys.
|
||||
* Currently only supports generating ECC keys.
|
||||
*/
|
||||
/* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
#include "test/drivers/keygen.h"
|
||||
|
||||
#include "test/random.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
test_driver_keygen_hooks_t test_driver_keygen_hooks = TEST_DRIVER_KEYGEN_INIT;
|
||||
|
||||
psa_status_t test_transparent_generate_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *key, size_t key_size, size_t *key_length )
|
||||
{
|
||||
++test_driver_keygen_hooks.hits;
|
||||
|
||||
if( test_driver_keygen_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_keygen_hooks.forced_status );
|
||||
|
||||
if( test_driver_keygen_hooks.forced_output != NULL )
|
||||
{
|
||||
if( test_driver_keygen_hooks.forced_output_length > key_size )
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
memcpy( key, test_driver_keygen_hooks.forced_output,
|
||||
test_driver_keygen_hooks.forced_output_length );
|
||||
*key_length = test_driver_keygen_hooks.forced_output_length;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
/* Copied from psa_crypto.c */
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
|
||||
&& PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
|
||||
{
|
||||
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( psa_get_key_type( attributes ) );
|
||||
mbedtls_ecp_group_id grp_id =
|
||||
mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
|
||||
const mbedtls_ecp_curve_info *curve_info =
|
||||
mbedtls_ecp_curve_info_from_grp_id( grp_id );
|
||||
mbedtls_ecp_keypair ecp;
|
||||
mbedtls_test_rnd_pseudo_info rnd_info;
|
||||
memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
if( attributes->domain_parameters_size != 0 )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
if( curve_info->bit_size != psa_get_key_bits( attributes ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
mbedtls_ecp_keypair_init( &ecp );
|
||||
ret = mbedtls_ecp_gen_key( grp_id, &ecp,
|
||||
&mbedtls_test_rnd_pseudo_rand,
|
||||
&rnd_info );
|
||||
if( ret != 0 )
|
||||
{
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( mbedtls_to_psa_error( ret ) );
|
||||
}
|
||||
|
||||
/* Make sure to use export representation */
|
||||
size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) );
|
||||
if( key_size < bytes )
|
||||
{
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
}
|
||||
psa_status_t status = mbedtls_to_psa_error(
|
||||
mbedtls_mpi_write_binary( &ecp.d, key, bytes ) );
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
*key_length = bytes;
|
||||
}
|
||||
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( status );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_generate_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *key, size_t key_size, size_t *key_length )
|
||||
{
|
||||
(void) attributes;
|
||||
(void) key;
|
||||
(void) key_size;
|
||||
(void) key_length;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
|
@ -40,6 +40,25 @@ generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS
|
||||
generate_key through transparent driver: error
|
||||
generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR
|
||||
|
||||
validate key through transparent driver: good private key
|
||||
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
validate_key:PSA_SUCCESS:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_SUCCESS
|
||||
|
||||
validate key through transparent driver: good public key
|
||||
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
validate_key:PSA_SUCCESS:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_SUCCESS
|
||||
|
||||
validate key through transparent driver: fallback private key
|
||||
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
validate_key:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_SUCCESS
|
||||
|
||||
validate key through transparent driver: fallback public key
|
||||
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
validate_key:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_SUCCESS
|
||||
|
||||
validate key through transparent driver: error
|
||||
validate_key:PSA_ERROR_GENERIC_ERROR:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ERROR_GENERIC_ERROR
|
||||
|
||||
PSA symmetric encrypt: AES-CTR, 16 bytes, good
|
||||
depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
|
||||
cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
|
||||
|
@ -132,7 +132,7 @@ void generate_key( int force_status_arg,
|
||||
psa_status_t actual_status;
|
||||
uint8_t actual_output[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)] = {0};
|
||||
size_t actual_output_length;
|
||||
test_driver_keygen_hooks = test_driver_keygen_hooks_init();
|
||||
test_driver_key_management_hooks = test_driver_key_management_hooks_init();
|
||||
|
||||
psa_set_key_type( &attributes,
|
||||
PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
|
||||
@ -142,18 +142,18 @@ void generate_key( int force_status_arg,
|
||||
|
||||
if( fake_output->len > 0 )
|
||||
{
|
||||
expected_output = test_driver_keygen_hooks.forced_output = fake_output->x;
|
||||
expected_output_length = test_driver_keygen_hooks.forced_output_length =
|
||||
expected_output = test_driver_key_management_hooks.forced_output = fake_output->x;
|
||||
expected_output_length = test_driver_key_management_hooks.forced_output_length =
|
||||
fake_output->len;
|
||||
}
|
||||
|
||||
test_driver_keygen_hooks.hits = 0;
|
||||
test_driver_keygen_hooks.forced_status = force_status;
|
||||
test_driver_key_management_hooks.hits = 0;
|
||||
test_driver_key_management_hooks.forced_status = force_status;
|
||||
|
||||
PSA_ASSERT( psa_crypto_init( ) );
|
||||
|
||||
actual_status = psa_generate_key( &attributes, &handle );
|
||||
TEST_EQUAL( test_driver_keygen_hooks.hits, 1 );
|
||||
TEST_EQUAL( test_driver_key_management_hooks.hits, 1 );
|
||||
TEST_EQUAL( actual_status, expected_status );
|
||||
|
||||
if( actual_status == PSA_SUCCESS )
|
||||
@ -180,7 +180,41 @@ exit:
|
||||
psa_reset_key_attributes( &attributes );
|
||||
psa_destroy_key( handle );
|
||||
PSA_DONE( );
|
||||
test_driver_keygen_hooks = test_driver_keygen_hooks_init();
|
||||
test_driver_key_management_hooks = test_driver_key_management_hooks_init();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */
|
||||
void validate_key( int force_status_arg,
|
||||
int key_type_arg,
|
||||
data_t *key_input,
|
||||
int expected_status_arg )
|
||||
{
|
||||
psa_status_t force_status = force_status_arg;
|
||||
psa_status_t expected_status = expected_status_arg;
|
||||
psa_key_type_t key_type = key_type_arg;
|
||||
psa_key_handle_t handle = 0;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_status_t actual_status;
|
||||
test_driver_key_management_hooks = test_driver_key_management_hooks_init();
|
||||
|
||||
psa_set_key_type( &attributes,
|
||||
key_type );
|
||||
psa_set_key_bits( &attributes, 0 );
|
||||
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
|
||||
|
||||
test_driver_key_management_hooks.forced_status = force_status;
|
||||
|
||||
PSA_ASSERT( psa_crypto_init( ) );
|
||||
|
||||
actual_status = psa_import_key( &attributes, key_input->x, key_input->len, &handle );
|
||||
TEST_EQUAL( test_driver_key_management_hooks.hits, 1 );
|
||||
TEST_EQUAL( actual_status, expected_status );
|
||||
exit:
|
||||
psa_reset_key_attributes( &attributes );
|
||||
psa_destroy_key( handle );
|
||||
PSA_DONE( );
|
||||
test_driver_key_management_hooks = test_driver_key_management_hooks_init();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
|
@ -241,7 +241,7 @@
|
||||
<ClInclude Include="..\..\tests\include\test\psa_helpers.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\random.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\drivers\keygen.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\drivers\key_management.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\drivers\signature.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\drivers\size.h" />
|
||||
<ClInclude Include="..\..\tests\include\test\drivers\test_driver.h" />
|
||||
|
Loading…
Reference in New Issue
Block a user