mirror of
https://github.com/yuzu-mirror/mbedtls.git
synced 2026-04-04 22:19:05 +00:00
Merge remote-tracking branch 'origin/development' into development_new
Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
Conflicts:
include/mbedtls/check_config.h: nearby edits
library/entropy.c: nearby edits
programs/random/gen_random_havege.c: modification vs. removal
programs/ssl/ssl_test_lib.h: nearby edits
programs/test/cpp_dummy_build.cpp: nearby edits
visualc/VS2010/mbedTLS.vcxproj: automatically generated file,
regenerated with scripts/generate_visualc_files.pl
This commit is contained in:
commit
73e3e2cb1a
217 changed files with 23474 additions and 8202 deletions
74
tests/src/asn1_helpers.c
Normal file
74
tests/src/asn1_helpers.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/** \file asn1_helpers.c
|
||||
*
|
||||
* \brief Helper functions for tests that manipulate ASN.1 data.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <test/helpers.h>
|
||||
#include <test/macros.h>
|
||||
|
||||
#if defined(MBEDTLS_ASN1_PARSE_C)
|
||||
|
||||
#include <mbedtls/asn1.h>
|
||||
|
||||
int mbedtls_test_asn1_skip_integer( unsigned char **p, const unsigned char *end,
|
||||
size_t min_bits, size_t max_bits,
|
||||
int must_be_odd )
|
||||
{
|
||||
size_t len;
|
||||
size_t actual_bits;
|
||||
unsigned char msb;
|
||||
TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len,
|
||||
MBEDTLS_ASN1_INTEGER ),
|
||||
0 );
|
||||
|
||||
/* Check if the retrieved length doesn't extend the actual buffer's size.
|
||||
* It is assumed here, that end >= p, which validates casting to size_t. */
|
||||
TEST_ASSERT( len <= (size_t)( end - *p) );
|
||||
|
||||
/* Tolerate a slight departure from DER encoding:
|
||||
* - 0 may be represented by an empty string or a 1-byte string.
|
||||
* - The sign bit may be used as a value bit. */
|
||||
if( ( len == 1 && ( *p )[0] == 0 ) ||
|
||||
( len > 1 && ( *p )[0] == 0 && ( ( *p )[1] & 0x80 ) != 0 ) )
|
||||
{
|
||||
++( *p );
|
||||
--len;
|
||||
}
|
||||
if( min_bits == 0 && len == 0 )
|
||||
return( 1 );
|
||||
msb = ( *p )[0];
|
||||
TEST_ASSERT( msb != 0 );
|
||||
actual_bits = 8 * ( len - 1 );
|
||||
while( msb != 0 )
|
||||
{
|
||||
msb >>= 1;
|
||||
++actual_bits;
|
||||
}
|
||||
TEST_ASSERT( actual_bits >= min_bits );
|
||||
TEST_ASSERT( actual_bits <= max_bits );
|
||||
if( must_be_odd )
|
||||
TEST_ASSERT( ( ( *p )[len-1] & 1 ) != 0 );
|
||||
*p += len;
|
||||
return( 1 );
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ASN1_PARSE_C */
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_cipher.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "mbedtls/cipher.h"
|
||||
|
||||
|
|
@ -204,212 +205,85 @@ psa_status_t test_transparent_cipher_decrypt(
|
|||
output, output_size, output_length) );
|
||||
}
|
||||
|
||||
static psa_status_t test_transparent_cipher_setup(
|
||||
mbedtls_operation_t direction,
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
psa_status_t test_transparent_cipher_encrypt_setup(
|
||||
mbedtls_transparent_test_driver_cipher_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
||||
int ret = 0;
|
||||
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( operation->alg != 0 )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
/* Wiping the entire struct here, instead of member-by-member. This is useful
|
||||
* for the test suite, since it gives a chance of catching memory corruption
|
||||
* errors should the core not have allocated (enough) memory for our context
|
||||
* struct. */
|
||||
/* Wiping the entire struct here, instead of member-by-member. This is
|
||||
* useful for the test suite, since it gives a chance of catching memory
|
||||
* corruption errors should the core not have allocated (enough) memory for
|
||||
* our context struct. */
|
||||
memset( operation, 0, sizeof( *operation ) );
|
||||
|
||||
/* Allow overriding return value for testing purposes */
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
/* Test driver supports AES-CTR only, to verify operation calls. */
|
||||
if( alg != PSA_ALG_CTR ||
|
||||
psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
|
||||
operation->alg = alg;
|
||||
operation->iv_size = 16;
|
||||
|
||||
cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES,
|
||||
key_length * 8,
|
||||
MBEDTLS_MODE_CTR );
|
||||
if( cipher_info == NULL )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
|
||||
mbedtls_cipher_init( &operation->cipher );
|
||||
ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
|
||||
if( ret != 0 ) {
|
||||
mbedtls_cipher_free( &operation->cipher );
|
||||
return( mbedtls_to_psa_error( ret ) );
|
||||
}
|
||||
|
||||
ret = mbedtls_cipher_setkey( &operation->cipher,
|
||||
key,
|
||||
key_length * 8, direction );
|
||||
if( ret != 0 ) {
|
||||
mbedtls_cipher_free( &operation->cipher );
|
||||
return( mbedtls_to_psa_error( ret ) );
|
||||
}
|
||||
|
||||
operation->iv_set = 0;
|
||||
operation->iv_required = 1;
|
||||
operation->key_set = 1;
|
||||
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_encrypt_setup(
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
return ( test_transparent_cipher_setup( MBEDTLS_ENCRYPT,
|
||||
operation,
|
||||
attributes,
|
||||
key,
|
||||
key_length,
|
||||
alg ) );
|
||||
return ( mbedtls_transparent_test_driver_cipher_encrypt_setup(
|
||||
operation, attributes, key, key_length, alg ) );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_decrypt_setup(
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
mbedtls_transparent_test_driver_cipher_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
return ( test_transparent_cipher_setup( MBEDTLS_DECRYPT,
|
||||
operation,
|
||||
attributes,
|
||||
key,
|
||||
key_length,
|
||||
alg ) );
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
return ( mbedtls_transparent_test_driver_cipher_decrypt_setup(
|
||||
operation, attributes, key, key_length, alg ) );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_abort(
|
||||
test_transparent_cipher_operation_t *operation)
|
||||
mbedtls_transparent_test_driver_cipher_operation_t *operation)
|
||||
{
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( operation->alg == 0 )
|
||||
return( PSA_SUCCESS );
|
||||
if( operation->alg != PSA_ALG_CTR )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
mbedtls_cipher_free( &operation->cipher );
|
||||
mbedtls_transparent_test_driver_cipher_abort( operation );
|
||||
|
||||
/* Wiping the entire struct here, instead of member-by-member. This is useful
|
||||
* for the test suite, since it gives a chance of catching memory corruption
|
||||
* errors should the core not have allocated (enough) memory for our context
|
||||
* struct. */
|
||||
/* Wiping the entire struct here, instead of member-by-member. This is
|
||||
* useful for the test suite, since it gives a chance of catching memory
|
||||
* corruption errors should the core not have allocated (enough) memory for
|
||||
* our context struct. */
|
||||
memset( operation, 0, sizeof( *operation ) );
|
||||
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_generate_iv(
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
uint8_t *iv,
|
||||
size_t iv_size,
|
||||
size_t *iv_length)
|
||||
{
|
||||
psa_status_t status;
|
||||
mbedtls_test_rnd_pseudo_info rnd_info;
|
||||
memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
||||
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
if( operation->alg != PSA_ALG_CTR )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( operation->iv_set || ! operation->iv_required )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( iv_size < operation->iv_size )
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_test_rnd_pseudo_rand( &rnd_info,
|
||||
iv,
|
||||
operation->iv_size ) );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
*iv_length = operation->iv_size;
|
||||
status = test_transparent_cipher_set_iv( operation, iv, *iv_length );
|
||||
|
||||
return( status );
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_set_iv(
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
mbedtls_transparent_test_driver_cipher_operation_t *operation,
|
||||
const uint8_t *iv,
|
||||
size_t iv_length)
|
||||
{
|
||||
psa_status_t status;
|
||||
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
if( operation->alg != PSA_ALG_CTR )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( operation->iv_set || ! operation->iv_required )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( iv_length != operation->iv_size )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_cipher_set_iv( &operation->cipher, iv, iv_length ) );
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
operation->iv_set = 1;
|
||||
|
||||
return( status );
|
||||
return( mbedtls_transparent_test_driver_cipher_set_iv(
|
||||
operation, iv, iv_length ) );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_update(
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
mbedtls_transparent_test_driver_cipher_operation_t *operation,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
psa_status_t status;
|
||||
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
if( operation->alg != PSA_ALG_CTR )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
/* CTR is a stream cipher, so data in and out are always the same size */
|
||||
if( output_size < input_length )
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_cipher_update( &operation->cipher, input,
|
||||
input_length, output, output_length ) );
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
return status;
|
||||
|
||||
if( test_driver_cipher_hooks.forced_output != NULL )
|
||||
{
|
||||
if( output_size < test_driver_cipher_hooks.forced_output_length )
|
||||
|
|
@ -419,52 +293,26 @@ psa_status_t test_transparent_cipher_update(
|
|||
test_driver_cipher_hooks.forced_output,
|
||||
test_driver_cipher_hooks.forced_output_length );
|
||||
*output_length = test_driver_cipher_hooks.forced_output_length;
|
||||
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
}
|
||||
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
return( mbedtls_transparent_test_driver_cipher_update(
|
||||
operation, input, input_length,
|
||||
output, output_size, output_length ) );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_cipher_finish(
|
||||
test_transparent_cipher_operation_t *operation,
|
||||
mbedtls_transparent_test_driver_cipher_operation_t *operation,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
|
||||
|
||||
test_driver_cipher_hooks.hits++;
|
||||
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
if( operation->alg != PSA_ALG_CTR )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( ! operation->key_set )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( operation->iv_required && ! operation->iv_set )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_cipher_finish( &operation->cipher,
|
||||
temp_output_buffer,
|
||||
output_length ) );
|
||||
|
||||
mbedtls_cipher_free( &operation->cipher );
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
if( *output_length == 0 )
|
||||
; /* Nothing to copy. Note that output may be NULL in this case. */
|
||||
else if( output_size >= *output_length )
|
||||
memcpy( output, temp_output_buffer, *output_length );
|
||||
else
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
|
||||
|
||||
if( test_driver_cipher_hooks.forced_output != NULL )
|
||||
{
|
||||
if( output_size < test_driver_cipher_hooks.forced_output_length )
|
||||
|
|
@ -474,9 +322,15 @@ psa_status_t test_transparent_cipher_finish(
|
|||
test_driver_cipher_hooks.forced_output,
|
||||
test_driver_cipher_hooks.forced_output_length );
|
||||
*output_length = test_driver_cipher_hooks.forced_output_length;
|
||||
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
}
|
||||
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_cipher_hooks.forced_status );
|
||||
|
||||
return( mbedtls_transparent_test_driver_cipher_finish(
|
||||
operation, output, output_size, output_length ) );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -521,7 +375,7 @@ psa_status_t test_opaque_cipher_decrypt(
|
|||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_encrypt_setup(
|
||||
test_opaque_cipher_operation_t *operation,
|
||||
mbedtls_opaque_test_driver_cipher_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
psa_algorithm_t alg)
|
||||
|
|
@ -535,7 +389,7 @@ psa_status_t test_opaque_cipher_encrypt_setup(
|
|||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_decrypt_setup(
|
||||
test_opaque_cipher_operation_t *operation,
|
||||
mbedtls_opaque_test_driver_cipher_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
psa_algorithm_t alg)
|
||||
|
|
@ -549,27 +403,14 @@ psa_status_t test_opaque_cipher_decrypt_setup(
|
|||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_abort(
|
||||
test_opaque_cipher_operation_t *operation)
|
||||
mbedtls_opaque_test_driver_cipher_operation_t *operation )
|
||||
{
|
||||
(void) operation;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_generate_iv(
|
||||
test_opaque_cipher_operation_t *operation,
|
||||
uint8_t *iv,
|
||||
size_t iv_size,
|
||||
size_t *iv_length)
|
||||
{
|
||||
(void) operation;
|
||||
(void) iv;
|
||||
(void) iv_size;
|
||||
(void) iv_length;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_set_iv(
|
||||
test_opaque_cipher_operation_t *operation,
|
||||
mbedtls_opaque_test_driver_cipher_operation_t *operation,
|
||||
const uint8_t *iv,
|
||||
size_t iv_length)
|
||||
{
|
||||
|
|
@ -580,7 +421,7 @@ psa_status_t test_opaque_cipher_set_iv(
|
|||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_update(
|
||||
test_opaque_cipher_operation_t *operation,
|
||||
mbedtls_opaque_test_driver_cipher_operation_t *operation,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *output,
|
||||
|
|
@ -597,7 +438,7 @@ psa_status_t test_opaque_cipher_update(
|
|||
}
|
||||
|
||||
psa_status_t test_opaque_cipher_finish(
|
||||
test_opaque_cipher_operation_t *operation,
|
||||
mbedtls_opaque_test_driver_cipher_operation_t *operation,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "psa_crypto_ecp.h"
|
||||
#include "psa_crypto_rsa.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
|
|
@ -43,11 +45,6 @@ psa_status_t test_transparent_generate_key(
|
|||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *key, size_t key_size, size_t *key_length )
|
||||
{
|
||||
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \
|
||||
!defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
|
||||
(void)attributes;
|
||||
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR &&
|
||||
* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
|
||||
++test_driver_key_management_hooks.hits;
|
||||
|
||||
if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
|
||||
|
|
@ -64,66 +61,26 @@ psa_status_t test_transparent_generate_key(
|
|||
}
|
||||
|
||||
/* Copied from psa_crypto.c */
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
|
||||
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 );
|
||||
return( mbedtls_transparent_test_driver_ecp_generate_key(
|
||||
attributes, key, key_size, key_length ) );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
|
||||
* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) */
|
||||
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
|
||||
if ( psa_get_key_type( attributes ) == PSA_KEY_TYPE_RSA_KEY_PAIR )
|
||||
return( mbedtls_transparent_test_driver_rsa_generate_key(
|
||||
attributes, key, key_size, key_length ) );
|
||||
else
|
||||
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) */
|
||||
{
|
||||
(void)attributes;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_generate_key(
|
||||
|
|
@ -137,121 +94,78 @@ psa_status_t test_opaque_generate_key(
|
|||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_validate_key(
|
||||
psa_status_t test_transparent_import_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
size_t *bits )
|
||||
uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
size_t *key_buffer_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 );
|
||||
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_type_t type = psa_get_key_type( attributes );
|
||||
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
|
||||
psa_key_type_t type = psa_get_key_type( attributes );
|
||||
if ( PSA_KEY_TYPE_IS_ECC( type ) )
|
||||
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 );
|
||||
status = mbedtls_transparent_test_driver_ecp_import_key(
|
||||
attributes,
|
||||
data, data_length,
|
||||
key_buffer, key_buffer_size,
|
||||
key_buffer_length, bits );
|
||||
}
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
|
||||
if( PSA_KEY_TYPE_IS_RSA( type ) )
|
||||
{
|
||||
status = mbedtls_transparent_test_driver_rsa_import_key(
|
||||
attributes,
|
||||
data, data_length,
|
||||
key_buffer, key_buffer_size,
|
||||
key_buffer_length, bits );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
(void)data;
|
||||
(void)data_length;
|
||||
(void)key_buffer;
|
||||
(void)key_buffer_size;
|
||||
(void)key_buffer_length;
|
||||
(void)bits;
|
||||
(void)type;
|
||||
}
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_export_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
uint8_t *data, size_t data_size, size_t *data_length )
|
||||
{
|
||||
(void) attributes;
|
||||
(void) key;
|
||||
(void) key_length;
|
||||
(void) data;
|
||||
(void) data_size;
|
||||
(void) data_length;
|
||||
(void) bits;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
|
||||
* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_export_public_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
uint8_t *data, size_t data_size, size_t *data_length )
|
||||
{
|
||||
++test_driver_key_management_hooks.hits;
|
||||
|
|
@ -269,73 +183,39 @@ psa_status_t test_transparent_export_public_key(
|
|||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
if( key == NULL || key_length == 0 )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
psa_key_type_t keytype = psa_get_key_type( attributes );
|
||||
(void) keytype;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_type_t key_type = psa_get_key_type( attributes );
|
||||
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
|
||||
if( PSA_KEY_TYPE_IS_ECC( keytype ) )
|
||||
if( PSA_KEY_TYPE_IS_ECC( key_type ) )
|
||||
{
|
||||
if( !PSA_KEY_TYPE_IS_KEY_PAIR( keytype ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
/* Mostly copied from psa_crypto.c */
|
||||
mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_ecp_keypair ecp;
|
||||
mbedtls_test_rnd_pseudo_info rnd_info;
|
||||
memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
||||
|
||||
if( attributes->domain_parameters_size != 0 )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
|
||||
grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( keytype ),
|
||||
PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
|
||||
if( grp_id == MBEDTLS_ECP_DP_NONE )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
|
||||
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;
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_read_key( ecp.grp.id,
|
||||
&ecp,
|
||||
key,
|
||||
key_length ) );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto ecp_exit;
|
||||
|
||||
/* Calculate the public key */
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G,
|
||||
&mbedtls_test_rnd_pseudo_rand,
|
||||
&rnd_info ) );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto ecp_exit;
|
||||
|
||||
status = mbedtls_to_psa_error(
|
||||
mbedtls_ecp_point_write_binary( &ecp.grp, &ecp.Q,
|
||||
MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||
data_length,
|
||||
data,
|
||||
data_size ) );
|
||||
if( status != PSA_SUCCESS )
|
||||
memset( data, 0, data_size );
|
||||
ecp_exit:
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
return( status );
|
||||
status = mbedtls_transparent_test_driver_ecp_export_public_key(
|
||||
attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
data, data_size, data_length );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
|
||||
if( PSA_KEY_TYPE_IS_RSA( key_type ) )
|
||||
{
|
||||
status = mbedtls_transparent_test_driver_rsa_export_public_key(
|
||||
attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
data, data_size, data_length );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
(void)key_buffer;
|
||||
(void)key_buffer_size;
|
||||
(void)key_type;
|
||||
}
|
||||
#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
|
||||
* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
|
||||
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
return( status );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_export_public_key(
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "psa_crypto_ecp.h"
|
||||
#include "psa_crypto_rsa.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
|
||||
#include "test/drivers/signature.h"
|
||||
|
|
@ -44,7 +46,7 @@ test_driver_signature_hooks_t test_driver_signature_verify_hooks = TEST_DRIVER_S
|
|||
|
||||
psa_status_t test_transparent_signature_sign_hash(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash, size_t hash_length,
|
||||
uint8_t *signature, size_t signature_size, size_t *signature_length )
|
||||
|
|
@ -64,85 +66,58 @@ psa_status_t test_transparent_signature_sign_hash(
|
|||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
|
||||
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
|
||||
if( attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
|
||||
{
|
||||
return( mbedtls_transparent_test_driver_rsa_sign_hash(
|
||||
attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, hash, hash_length,
|
||||
signature, signature_size, signature_length ) );
|
||||
}
|
||||
else
|
||||
#endif /* defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) ||
|
||||
* defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) */
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
|
||||
defined(MBEDTLS_SHA256_C)
|
||||
if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) )
|
||||
#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
|
||||
if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) )
|
||||
{
|
||||
if(
|
||||
#if defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
|
||||
PSA_ALG_IS_ECDSA( alg )
|
||||
#else
|
||||
PSA_ALG_IS_RANDOMIZED_ECDSA( alg )
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return( mbedtls_transparent_test_driver_ecdsa_sign_hash(
|
||||
attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, hash, hash_length,
|
||||
signature, signature_size, signature_length ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) ||
|
||||
* defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) */
|
||||
{
|
||||
(void)attributes;
|
||||
(void)key_buffer;
|
||||
(void)key_buffer_size;
|
||||
(void)alg;
|
||||
(void)hash;
|
||||
(void)hash_length;
|
||||
(void)signature;
|
||||
(void)signature_size;
|
||||
(void)signature_length;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
switch( psa_get_key_type( attributes ) )
|
||||
{
|
||||
case PSA_ECC_CURVE_SECP_R1:
|
||||
switch( psa_get_key_bits( attributes ) )
|
||||
{
|
||||
case 256:
|
||||
grp_id = MBEDTLS_ECP_DP_SECP256R1;
|
||||
break;
|
||||
case 384:
|
||||
grp_id = MBEDTLS_ECP_DP_SECP384R1;
|
||||
break;
|
||||
case 521:
|
||||
grp_id = MBEDTLS_ECP_DP_SECP521R1;
|
||||
break;
|
||||
default:
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
/* Beyond this point, the driver is actually doing the work of
|
||||
* calculating the signature. */
|
||||
|
||||
status = PSA_ERROR_GENERIC_ERROR;
|
||||
int ret = 0;
|
||||
mbedtls_mpi r, s;
|
||||
mbedtls_mpi_init( &r );
|
||||
mbedtls_mpi_init( &s );
|
||||
mbedtls_ecp_keypair ecp;
|
||||
mbedtls_ecp_keypair_init( &ecp );
|
||||
size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
|
||||
key, key_length ) );
|
||||
|
||||
/* Code adapted from psa_ecdsa_sign() in psa_crypto.c. */
|
||||
mbedtls_md_type_t md_alg = MBEDTLS_MD_SHA256;
|
||||
if( signature_size < 2 * curve_bytes )
|
||||
{
|
||||
status = PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
goto cleanup;
|
||||
}
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ecp.grp, &r, &s, &ecp.d,
|
||||
hash, hash_length, md_alg ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
|
||||
signature,
|
||||
curve_bytes ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
|
||||
signature + curve_bytes,
|
||||
curve_bytes ) );
|
||||
cleanup:
|
||||
status = mbedtls_to_psa_error( ret );
|
||||
mbedtls_mpi_free( &r );
|
||||
mbedtls_mpi_free( &s );
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
if( status == PSA_SUCCESS )
|
||||
*signature_length = 2 * curve_bytes;
|
||||
#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
|
||||
defined(MBEDTLS_SHA256_C) */
|
||||
(void) attributes;
|
||||
(void) key;
|
||||
(void) key_length;
|
||||
(void) alg;
|
||||
(void) hash;
|
||||
(void) hash_length;
|
||||
#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
|
||||
defined(MBEDTLS_SHA256_C) */
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_signature_sign_hash(
|
||||
|
|
@ -161,12 +136,13 @@ psa_status_t test_opaque_signature_sign_hash(
|
|||
(void) signature;
|
||||
(void) signature_size;
|
||||
(void) signature_length;
|
||||
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
psa_status_t test_transparent_signature_verify_hash(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
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 )
|
||||
|
|
@ -176,98 +152,52 @@ psa_status_t test_transparent_signature_verify_hash(
|
|||
if( test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS )
|
||||
return( test_driver_signature_verify_hooks.forced_status );
|
||||
|
||||
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
|
||||
defined(MBEDTLS_SHA256_C)
|
||||
if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
switch( psa_get_key_type( attributes ) )
|
||||
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
|
||||
if( PSA_KEY_TYPE_IS_RSA( attributes->core.type ) )
|
||||
{
|
||||
case PSA_ECC_CURVE_SECP_R1:
|
||||
switch( psa_get_key_bits( attributes ) )
|
||||
{
|
||||
case 256:
|
||||
grp_id = MBEDTLS_ECP_DP_SECP256R1;
|
||||
break;
|
||||
case 384:
|
||||
grp_id = MBEDTLS_ECP_DP_SECP384R1;
|
||||
break;
|
||||
case 521:
|
||||
grp_id = MBEDTLS_ECP_DP_SECP521R1;
|
||||
break;
|
||||
default:
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
return( mbedtls_transparent_test_driver_rsa_verify_hash(
|
||||
attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, hash, hash_length,
|
||||
signature, signature_length ) );
|
||||
}
|
||||
|
||||
/* Beyond this point, the driver is actually doing the work of
|
||||
* calculating the signature. */
|
||||
|
||||
status = PSA_ERROR_GENERIC_ERROR;
|
||||
int ret = 0;
|
||||
mbedtls_mpi r, s;
|
||||
mbedtls_mpi_init( &r );
|
||||
mbedtls_mpi_init( &s );
|
||||
mbedtls_ecp_keypair ecp;
|
||||
mbedtls_ecp_keypair_init( &ecp );
|
||||
mbedtls_test_rnd_pseudo_info rnd_info;
|
||||
memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
||||
size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
|
||||
|
||||
/* Code adapted from psa_ecdsa_verify() in psa_crypto.c. */
|
||||
if( signature_length < 2 * curve_bytes )
|
||||
{
|
||||
status = PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
|
||||
signature,
|
||||
curve_bytes ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
|
||||
signature + curve_bytes,
|
||||
curve_bytes ) );
|
||||
|
||||
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( attributes ) ) )
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
|
||||
key, key_length ) );
|
||||
else
|
||||
#endif /* defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) ||
|
||||
* defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) */
|
||||
|
||||
#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
|
||||
if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) )
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ecp.d, key, key_length ) );
|
||||
MBEDTLS_MPI_CHK(
|
||||
mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G,
|
||||
&mbedtls_test_rnd_pseudo_rand,
|
||||
&rnd_info ) );
|
||||
if( PSA_ALG_IS_ECDSA( alg ) )
|
||||
{
|
||||
return( mbedtls_transparent_test_driver_ecdsa_verify_hash(
|
||||
attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, hash, hash_length,
|
||||
signature, signature_length ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) ||
|
||||
* defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) */
|
||||
{
|
||||
(void)attributes;
|
||||
(void)key_buffer;
|
||||
(void)key_buffer_size;
|
||||
(void)alg;
|
||||
(void)hash;
|
||||
(void)hash_length;
|
||||
(void)signature;
|
||||
(void)signature_length;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecdsa_verify( &ecp.grp, hash, hash_length,
|
||||
&ecp.Q, &r, &s ) );
|
||||
cleanup:
|
||||
status = mbedtls_to_psa_error( ret );
|
||||
mbedtls_mpi_free( &r );
|
||||
mbedtls_mpi_free( &s );
|
||||
mbedtls_ecp_keypair_free( &ecp );
|
||||
#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
|
||||
defined(MBEDTLS_SHA256_C) */
|
||||
(void) attributes;
|
||||
(void) key;
|
||||
(void) key_length;
|
||||
(void) alg;
|
||||
(void) hash;
|
||||
(void) hash_length;
|
||||
(void) signature;
|
||||
(void) signature_length;
|
||||
#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
|
||||
defined(MBEDTLS_SHA256_C) */
|
||||
|
||||
return( status );
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
}
|
||||
|
||||
psa_status_t test_opaque_signature_verify_hash(
|
||||
|
|
|
|||
56
tests/src/fake_external_rng_for_test.c
Normal file
56
tests/src/fake_external_rng_for_test.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/** \file fake_external_rng_for_test.c
|
||||
*
|
||||
* \brief Helper functions to test PSA crypto functionality.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <test/fake_external_rng_for_test.h>
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
|
||||
#include <test/random.h>
|
||||
#include <psa/crypto.h>
|
||||
|
||||
static int test_insecure_external_rng_enabled = 0;
|
||||
|
||||
void mbedtls_test_enable_insecure_external_rng( void )
|
||||
{
|
||||
test_insecure_external_rng_enabled = 1;
|
||||
}
|
||||
|
||||
void mbedtls_test_disable_insecure_external_rng( void )
|
||||
{
|
||||
test_insecure_external_rng_enabled = 0;
|
||||
}
|
||||
|
||||
psa_status_t mbedtls_psa_external_get_random(
|
||||
mbedtls_psa_external_random_context_t *context,
|
||||
uint8_t *output, size_t output_size, size_t *output_length )
|
||||
{
|
||||
(void) context;
|
||||
|
||||
if( !test_insecure_external_rng_enabled )
|
||||
return( PSA_ERROR_INSUFFICIENT_ENTROPY );
|
||||
|
||||
/* This implementation is for test purposes only!
|
||||
* Use the libc non-cryptographic random generator. */
|
||||
mbedtls_test_rnd_std_rand( NULL, output, output_size );
|
||||
*output_length = output_size;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
|
||||
|
|
@ -44,6 +44,8 @@ static param_failed_ctx_t param_failed_ctx;
|
|||
static mbedtls_platform_context platform_ctx;
|
||||
#endif
|
||||
|
||||
mbedtls_test_info_t mbedtls_test_info;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
|
||||
|
|
@ -77,6 +79,42 @@ static int ascii2uc(const char c, unsigned char *uc)
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
void mbedtls_test_fail( const char *test, int line_no, const char* filename )
|
||||
{
|
||||
if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED )
|
||||
{
|
||||
/* We've already recorded the test as having failed. Don't
|
||||
* overwrite any previous information about the failure. */
|
||||
return;
|
||||
}
|
||||
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_FAILED;
|
||||
mbedtls_test_info.test = test;
|
||||
mbedtls_test_info.line_no = line_no;
|
||||
mbedtls_test_info.filename = filename;
|
||||
}
|
||||
|
||||
void mbedtls_test_skip( const char *test, int line_no, const char* filename )
|
||||
{
|
||||
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SKIPPED;
|
||||
mbedtls_test_info.test = test;
|
||||
mbedtls_test_info.line_no = line_no;
|
||||
mbedtls_test_info.filename = filename;
|
||||
}
|
||||
|
||||
void mbedtls_test_set_step( unsigned long step )
|
||||
{
|
||||
mbedtls_test_info.step = step;
|
||||
}
|
||||
|
||||
void mbedtls_test_info_reset( void )
|
||||
{
|
||||
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SUCCESS;
|
||||
mbedtls_test_info.step = (unsigned long)( -1 );
|
||||
mbedtls_test_info.test = 0;
|
||||
mbedtls_test_info.line_no = 0;
|
||||
mbedtls_test_info.filename = 0;
|
||||
}
|
||||
|
||||
int mbedtls_test_unhexify( unsigned char *obuf,
|
||||
size_t obufmax,
|
||||
const char *ibuf,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,51 @@
|
|||
|
||||
#include <psa/crypto.h>
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
|
||||
|
||||
#include <psa_crypto_storage.h>
|
||||
|
||||
static mbedtls_svc_key_id_t key_ids_used_in_test[9];
|
||||
static size_t num_key_ids_used;
|
||||
|
||||
int mbedtls_test_uses_key_id( mbedtls_svc_key_id_t key_id )
|
||||
{
|
||||
size_t i;
|
||||
if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id ) >
|
||||
PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
|
||||
{
|
||||
/* Don't touch key id values that designate non-key files. */
|
||||
return( 1 );
|
||||
}
|
||||
for( i = 0; i < num_key_ids_used ; i++ )
|
||||
{
|
||||
if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
|
||||
return( 1 );
|
||||
}
|
||||
if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
|
||||
return( 0 );
|
||||
key_ids_used_in_test[num_key_ids_used] = key_id;
|
||||
++num_key_ids_used;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
void mbedtls_test_psa_purge_key_storage( void )
|
||||
{
|
||||
size_t i;
|
||||
for( i = 0; i < num_key_ids_used; i++ )
|
||||
psa_destroy_persistent_key( key_ids_used_in_test[i] );
|
||||
num_key_ids_used = 0;
|
||||
}
|
||||
|
||||
void mbedtls_test_psa_purge_key_cache( void )
|
||||
{
|
||||
size_t i;
|
||||
for( i = 0; i < num_key_ids_used; i++ )
|
||||
psa_purge_key( key_ids_used_in_test[i] );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
|
||||
|
||||
const char *mbedtls_test_helper_is_psa_leaking( void )
|
||||
{
|
||||
mbedtls_psa_stats_t stats;
|
||||
|
|
@ -69,36 +114,4 @@ psa_status_t mbedtls_test_record_status( psa_status_t status,
|
|||
}
|
||||
#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
|
||||
#include <test/random.h>
|
||||
|
||||
static int test_insecure_external_rng_enabled = 0;
|
||||
|
||||
void mbedtls_test_enable_insecure_external_rng( void )
|
||||
{
|
||||
test_insecure_external_rng_enabled = 1;
|
||||
}
|
||||
|
||||
void mbedtls_test_disable_insecure_external_rng( void )
|
||||
{
|
||||
test_insecure_external_rng_enabled = 0;
|
||||
}
|
||||
|
||||
psa_status_t mbedtls_psa_external_get_random(
|
||||
mbedtls_psa_external_random_context_t *context,
|
||||
uint8_t *output, size_t output_size, size_t *output_length )
|
||||
{
|
||||
(void) context;
|
||||
|
||||
if( !test_insecure_external_rng_enabled )
|
||||
return( PSA_ERROR_INSUFFICIENT_ENTROPY );
|
||||
|
||||
/* This implementation is for test purposes only!
|
||||
* Use the libc non-cryptographic random generator. */
|
||||
mbedtls_test_rnd_std_rand( NULL, output, output_size );
|
||||
*output_length = output_size;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_C */
|
||||
|
|
|
|||
919
tests/src/psa_exercise_key.c
Normal file
919
tests/src/psa_exercise_key.c
Normal file
|
|
@ -0,0 +1,919 @@
|
|||
/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
|
||||
* and can do what it is supposed to do.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <test/helpers.h>
|
||||
#include <test/macros.h>
|
||||
#include <test/psa_exercise_key.h>
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_C)
|
||||
|
||||
#include <mbedtls/asn1.h>
|
||||
#include <psa/crypto.h>
|
||||
|
||||
#include <test/asn1_helpers.h>
|
||||
#include <test/psa_crypto_helpers.h>
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
|
||||
static int lifetime_is_dynamic_secure_element( psa_key_lifetime_t lifetime )
|
||||
{
|
||||
return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) !=
|
||||
PSA_KEY_LOCATION_LOCAL_STORAGE );
|
||||
}
|
||||
#endif
|
||||
|
||||
static int check_key_attributes_sanity( mbedtls_svc_key_id_t key )
|
||||
{
|
||||
int ok = 0;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_lifetime_t lifetime;
|
||||
mbedtls_svc_key_id_t id;
|
||||
psa_key_type_t type;
|
||||
size_t bits;
|
||||
|
||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||
lifetime = psa_get_key_lifetime( &attributes );
|
||||
id = psa_get_key_id( &attributes );
|
||||
type = psa_get_key_type( &attributes );
|
||||
bits = psa_get_key_bits( &attributes );
|
||||
|
||||
/* Persistence */
|
||||
if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
|
||||
{
|
||||
TEST_ASSERT(
|
||||
( PSA_KEY_ID_VOLATILE_MIN <=
|
||||
MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
|
||||
( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <=
|
||||
PSA_KEY_ID_VOLATILE_MAX ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ASSERT(
|
||||
( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
|
||||
( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
|
||||
}
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
|
||||
/* randomly-generated 64-bit constant, should never appear in test data */
|
||||
psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
|
||||
psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
|
||||
if( lifetime_is_dynamic_secure_element( lifetime ) )
|
||||
{
|
||||
/* Mbed Crypto currently always exposes the slot number to
|
||||
* applications. This is not mandated by the PSA specification
|
||||
* and may change in future versions. */
|
||||
TEST_EQUAL( status, 0 );
|
||||
TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Type and size */
|
||||
TEST_ASSERT( type != 0 );
|
||||
TEST_ASSERT( bits != 0 );
|
||||
TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
|
||||
if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
|
||||
TEST_ASSERT( bits % 8 == 0 );
|
||||
|
||||
/* MAX macros concerning specific key types */
|
||||
if( PSA_KEY_TYPE_IS_ECC( type ) )
|
||||
TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
|
||||
else if( PSA_KEY_TYPE_IS_RSA( type ) )
|
||||
TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
|
||||
TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) <= PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE );
|
||||
|
||||
ok = 1;
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Key attributes may have been returned by psa_get_key_attributes()
|
||||
* thus reset them as required.
|
||||
*/
|
||||
psa_reset_key_attributes( &attributes );
|
||||
|
||||
return( ok );
|
||||
}
|
||||
|
||||
static int exercise_mac_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
|
||||
const unsigned char input[] = "foo";
|
||||
unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
|
||||
size_t mac_length = sizeof( mac );
|
||||
|
||||
/* Convert wildcard algorithm to exercisable algorithm */
|
||||
if( alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG )
|
||||
{
|
||||
alg = PSA_ALG_TRUNCATED_MAC( alg, PSA_MAC_TRUNCATED_LENGTH( alg ) );
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_SIGN_HASH )
|
||||
{
|
||||
PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input, sizeof( input ) ) );
|
||||
PSA_ASSERT( psa_mac_sign_finish( &operation,
|
||||
mac, sizeof( mac ),
|
||||
&mac_length ) );
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_VERIFY_HASH )
|
||||
{
|
||||
psa_status_t verify_status =
|
||||
( usage & PSA_KEY_USAGE_SIGN_HASH ?
|
||||
PSA_SUCCESS :
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input, sizeof( input ) ) );
|
||||
TEST_EQUAL( psa_mac_verify_finish( &operation, mac, mac_length ),
|
||||
verify_status );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
psa_mac_abort( &operation );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exercise_cipher_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||
unsigned char iv[16] = {0};
|
||||
size_t iv_length = sizeof( iv );
|
||||
const unsigned char plaintext[16] = "Hello, world...";
|
||||
unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
|
||||
size_t ciphertext_length = sizeof( ciphertext );
|
||||
unsigned char decrypted[sizeof( ciphertext )];
|
||||
size_t part_length;
|
||||
|
||||
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
||||
{
|
||||
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_cipher_generate_iv( &operation,
|
||||
iv, sizeof( iv ),
|
||||
&iv_length ) );
|
||||
PSA_ASSERT( psa_cipher_update( &operation,
|
||||
plaintext, sizeof( plaintext ),
|
||||
ciphertext, sizeof( ciphertext ),
|
||||
&ciphertext_length ) );
|
||||
PSA_ASSERT( psa_cipher_finish( &operation,
|
||||
ciphertext + ciphertext_length,
|
||||
sizeof( ciphertext ) - ciphertext_length,
|
||||
&part_length ) );
|
||||
ciphertext_length += part_length;
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_DECRYPT )
|
||||
{
|
||||
psa_status_t status;
|
||||
int maybe_invalid_padding = 0;
|
||||
if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
|
||||
{
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||
/* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
|
||||
* have this macro yet. */
|
||||
iv_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(
|
||||
psa_get_key_type( &attributes ) );
|
||||
maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
|
||||
psa_reset_key_attributes( &attributes );
|
||||
}
|
||||
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_cipher_set_iv( &operation,
|
||||
iv, iv_length ) );
|
||||
PSA_ASSERT( psa_cipher_update( &operation,
|
||||
ciphertext, ciphertext_length,
|
||||
decrypted, sizeof( decrypted ),
|
||||
&part_length ) );
|
||||
status = psa_cipher_finish( &operation,
|
||||
decrypted + part_length,
|
||||
sizeof( decrypted ) - part_length,
|
||||
&part_length );
|
||||
/* For a stream cipher, all inputs are valid. For a block cipher,
|
||||
* if the input is some aribtrary data rather than an actual
|
||||
ciphertext, a padding error is likely. */
|
||||
if( maybe_invalid_padding )
|
||||
TEST_ASSERT( status == PSA_SUCCESS ||
|
||||
status == PSA_ERROR_INVALID_PADDING );
|
||||
else
|
||||
PSA_ASSERT( status );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
psa_cipher_abort( &operation );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exercise_aead_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
unsigned char nonce[16] = {0};
|
||||
size_t nonce_length = sizeof( nonce );
|
||||
unsigned char plaintext[16] = "Hello, world...";
|
||||
unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
|
||||
size_t ciphertext_length = sizeof( ciphertext );
|
||||
size_t plaintext_length = sizeof( ciphertext );
|
||||
|
||||
/* Convert wildcard algorithm to exercisable algorithm */
|
||||
if( alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG )
|
||||
{
|
||||
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) );
|
||||
}
|
||||
|
||||
/* Default IV length for AES-GCM is 12 bytes */
|
||||
if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
|
||||
PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
|
||||
{
|
||||
nonce_length = 12;
|
||||
}
|
||||
|
||||
/* IV length for CCM needs to be between 7 and 13 bytes */
|
||||
if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
|
||||
PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ) )
|
||||
{
|
||||
nonce_length = 12;
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
||||
{
|
||||
PSA_ASSERT( psa_aead_encrypt( key, alg,
|
||||
nonce, nonce_length,
|
||||
NULL, 0,
|
||||
plaintext, sizeof( plaintext ),
|
||||
ciphertext, sizeof( ciphertext ),
|
||||
&ciphertext_length ) );
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_DECRYPT )
|
||||
{
|
||||
psa_status_t verify_status =
|
||||
( usage & PSA_KEY_USAGE_ENCRYPT ?
|
||||
PSA_SUCCESS :
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
TEST_EQUAL( psa_aead_decrypt( key, alg,
|
||||
nonce, nonce_length,
|
||||
NULL, 0,
|
||||
ciphertext, ciphertext_length,
|
||||
plaintext, sizeof( plaintext ),
|
||||
&plaintext_length ),
|
||||
verify_status );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exercise_signature_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
|
||||
size_t payload_length = 16;
|
||||
unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
|
||||
size_t signature_length = sizeof( signature );
|
||||
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
|
||||
|
||||
/* If the policy allows signing with any hash, just pick one. */
|
||||
if( PSA_ALG_IS_HASH_AND_SIGN( alg ) && hash_alg == PSA_ALG_ANY_HASH )
|
||||
{
|
||||
#if defined(KNOWN_SUPPORTED_HASH_ALG)
|
||||
hash_alg = KNOWN_SUPPORTED_HASH_ALG;
|
||||
alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
|
||||
#else
|
||||
TEST_ASSERT( ! "No hash algorithm for hash-and-sign testing" );
|
||||
#endif
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_SIGN_HASH )
|
||||
{
|
||||
/* Some algorithms require the payload to have the size of
|
||||
* the hash encoded in the algorithm. Use this input size
|
||||
* even for algorithms that allow other input sizes. */
|
||||
if( hash_alg != 0 )
|
||||
payload_length = PSA_HASH_LENGTH( hash_alg );
|
||||
PSA_ASSERT( psa_sign_hash( key, alg,
|
||||
payload, payload_length,
|
||||
signature, sizeof( signature ),
|
||||
&signature_length ) );
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_VERIFY_HASH )
|
||||
{
|
||||
psa_status_t verify_status =
|
||||
( usage & PSA_KEY_USAGE_SIGN_HASH ?
|
||||
PSA_SUCCESS :
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
TEST_EQUAL( psa_verify_hash( key, alg,
|
||||
payload, payload_length,
|
||||
signature, signature_length ),
|
||||
verify_status );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
unsigned char plaintext[256] = "Hello, world...";
|
||||
unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
|
||||
size_t ciphertext_length = sizeof( ciphertext );
|
||||
size_t plaintext_length = 16;
|
||||
|
||||
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
||||
{
|
||||
PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
|
||||
plaintext, plaintext_length,
|
||||
NULL, 0,
|
||||
ciphertext, sizeof( ciphertext ),
|
||||
&ciphertext_length ) );
|
||||
}
|
||||
|
||||
if( usage & PSA_KEY_USAGE_DECRYPT )
|
||||
{
|
||||
psa_status_t status =
|
||||
psa_asymmetric_decrypt( key, alg,
|
||||
ciphertext, ciphertext_length,
|
||||
NULL, 0,
|
||||
plaintext, sizeof( plaintext ),
|
||||
&plaintext_length );
|
||||
TEST_ASSERT( status == PSA_SUCCESS ||
|
||||
( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
|
||||
( status == PSA_ERROR_INVALID_ARGUMENT ||
|
||||
status == PSA_ERROR_INVALID_PADDING ) ) );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_test_psa_setup_key_derivation_wrap(
|
||||
psa_key_derivation_operation_t* operation,
|
||||
mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const unsigned char* input1, size_t input1_length,
|
||||
const unsigned char* input2, size_t input2_length,
|
||||
size_t capacity )
|
||||
{
|
||||
PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
|
||||
if( PSA_ALG_IS_HKDF( alg ) )
|
||||
{
|
||||
PSA_ASSERT( psa_key_derivation_input_bytes( operation,
|
||||
PSA_KEY_DERIVATION_INPUT_SALT,
|
||||
input1, input1_length ) );
|
||||
PSA_ASSERT( psa_key_derivation_input_key( operation,
|
||||
PSA_KEY_DERIVATION_INPUT_SECRET,
|
||||
key ) );
|
||||
PSA_ASSERT( psa_key_derivation_input_bytes( operation,
|
||||
PSA_KEY_DERIVATION_INPUT_INFO,
|
||||
input2,
|
||||
input2_length ) );
|
||||
}
|
||||
else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
|
||||
PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
|
||||
{
|
||||
PSA_ASSERT( psa_key_derivation_input_bytes( operation,
|
||||
PSA_KEY_DERIVATION_INPUT_SEED,
|
||||
input1, input1_length ) );
|
||||
PSA_ASSERT( psa_key_derivation_input_key( operation,
|
||||
PSA_KEY_DERIVATION_INPUT_SECRET,
|
||||
key ) );
|
||||
PSA_ASSERT( psa_key_derivation_input_bytes( operation,
|
||||
PSA_KEY_DERIVATION_INPUT_LABEL,
|
||||
input2, input2_length ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ASSERT( ! "Key derivation algorithm not supported" );
|
||||
}
|
||||
|
||||
if( capacity != SIZE_MAX )
|
||||
PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
|
||||
unsigned char input1[] = "Input 1";
|
||||
size_t input1_length = sizeof( input1 );
|
||||
unsigned char input2[] = "Input 2";
|
||||
size_t input2_length = sizeof( input2 );
|
||||
unsigned char output[1];
|
||||
size_t capacity = sizeof( output );
|
||||
|
||||
if( usage & PSA_KEY_USAGE_DERIVE )
|
||||
{
|
||||
if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
|
||||
input1, input1_length,
|
||||
input2, input2_length,
|
||||
capacity ) )
|
||||
goto exit;
|
||||
|
||||
PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
|
||||
output,
|
||||
capacity ) );
|
||||
PSA_ASSERT( psa_key_derivation_abort( &operation ) );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* We need two keys to exercise key agreement. Exercise the
|
||||
* private key against its own public key. */
|
||||
psa_status_t mbedtls_test_psa_key_agreement_with_self(
|
||||
psa_key_derivation_operation_t *operation,
|
||||
mbedtls_svc_key_id_t key )
|
||||
{
|
||||
psa_key_type_t private_key_type;
|
||||
psa_key_type_t public_key_type;
|
||||
size_t key_bits;
|
||||
uint8_t *public_key = NULL;
|
||||
size_t public_key_length;
|
||||
/* Return GENERIC_ERROR if something other than the final call to
|
||||
* psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
|
||||
* but it's good enough: callers will report it as a failed test anyway. */
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||
private_key_type = psa_get_key_type( &attributes );
|
||||
key_bits = psa_get_key_bits( &attributes );
|
||||
public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
|
||||
public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
|
||||
ASSERT_ALLOC( public_key, public_key_length );
|
||||
PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
|
||||
&public_key_length ) );
|
||||
|
||||
status = psa_key_derivation_key_agreement(
|
||||
operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
|
||||
public_key, public_key_length );
|
||||
exit:
|
||||
/*
|
||||
* Key attributes may have been returned by psa_get_key_attributes()
|
||||
* thus reset them as required.
|
||||
*/
|
||||
psa_reset_key_attributes( &attributes );
|
||||
|
||||
mbedtls_free( public_key );
|
||||
return( status );
|
||||
}
|
||||
|
||||
/* We need two keys to exercise key agreement. Exercise the
|
||||
* private key against its own public key. */
|
||||
psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
|
||||
psa_algorithm_t alg,
|
||||
mbedtls_svc_key_id_t key )
|
||||
{
|
||||
psa_key_type_t private_key_type;
|
||||
psa_key_type_t public_key_type;
|
||||
size_t key_bits;
|
||||
uint8_t *public_key = NULL;
|
||||
size_t public_key_length;
|
||||
uint8_t output[1024];
|
||||
size_t output_length;
|
||||
/* Return GENERIC_ERROR if something other than the final call to
|
||||
* psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
|
||||
* but it's good enough: callers will report it as a failed test anyway. */
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||
private_key_type = psa_get_key_type( &attributes );
|
||||
key_bits = psa_get_key_bits( &attributes );
|
||||
public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
|
||||
public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
|
||||
ASSERT_ALLOC( public_key, public_key_length );
|
||||
PSA_ASSERT( psa_export_public_key( key,
|
||||
public_key, public_key_length,
|
||||
&public_key_length ) );
|
||||
|
||||
status = psa_raw_key_agreement( alg, key,
|
||||
public_key, public_key_length,
|
||||
output, sizeof( output ), &output_length );
|
||||
if ( status == PSA_SUCCESS )
|
||||
{
|
||||
TEST_ASSERT( output_length <=
|
||||
PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( private_key_type,
|
||||
key_bits ) );
|
||||
TEST_ASSERT( output_length <=
|
||||
PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
|
||||
}
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Key attributes may have been returned by psa_get_key_attributes()
|
||||
* thus reset them as required.
|
||||
*/
|
||||
psa_reset_key_attributes( &attributes );
|
||||
|
||||
mbedtls_free( public_key );
|
||||
return( status );
|
||||
}
|
||||
|
||||
static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
int ok = 0;
|
||||
|
||||
if( usage & PSA_KEY_USAGE_DERIVE )
|
||||
{
|
||||
/* We need two keys to exercise key agreement. Exercise the
|
||||
* private key against its own public key. */
|
||||
PSA_ASSERT( mbedtls_test_psa_raw_key_agreement_with_self( alg, key ) );
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
exit:
|
||||
return( ok );
|
||||
}
|
||||
|
||||
static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
|
||||
unsigned char output[1];
|
||||
int ok = 0;
|
||||
|
||||
if( usage & PSA_KEY_USAGE_DERIVE )
|
||||
{
|
||||
/* We need two keys to exercise key agreement. Exercise the
|
||||
* private key against its own public key. */
|
||||
PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
|
||||
PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
|
||||
PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
|
||||
output,
|
||||
sizeof( output ) ) );
|
||||
PSA_ASSERT( psa_key_derivation_abort( &operation ) );
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
exit:
|
||||
return( ok );
|
||||
}
|
||||
|
||||
int mbedtls_test_psa_exported_key_sanity_check(
|
||||
psa_key_type_t type, size_t bits,
|
||||
const uint8_t *exported, size_t exported_length )
|
||||
{
|
||||
TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits ) );
|
||||
|
||||
if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
|
||||
TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
|
||||
else
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
|
||||
if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
|
||||
{
|
||||
uint8_t *p = (uint8_t*) exported;
|
||||
const uint8_t *end = exported + exported_length;
|
||||
size_t len;
|
||||
/* RSAPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 0
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER, -- e
|
||||
* privateExponent INTEGER, -- d
|
||||
* prime1 INTEGER, -- p
|
||||
* prime2 INTEGER, -- q
|
||||
* exponent1 INTEGER, -- d mod (p-1)
|
||||
* exponent2 INTEGER, -- d mod (q-1)
|
||||
* coefficient INTEGER, -- (inverse of q) mod p
|
||||
* }
|
||||
*/
|
||||
TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_SEQUENCE |
|
||||
MBEDTLS_ASN1_CONSTRUCTED ), 0 );
|
||||
TEST_EQUAL( p + len, end );
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
|
||||
goto exit;
|
||||
/* Require d to be at least half the size of n. */
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
|
||||
goto exit;
|
||||
/* Require p and q to be at most half the size of n, rounded up. */
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
|
||||
goto exit;
|
||||
TEST_EQUAL( p, end );
|
||||
|
||||
TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
|
||||
{
|
||||
/* Just the secret value */
|
||||
TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
|
||||
|
||||
TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
|
||||
{
|
||||
uint8_t *p = (uint8_t*) exported;
|
||||
const uint8_t *end = exported + exported_length;
|
||||
size_t len;
|
||||
/* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER } -- e
|
||||
*/
|
||||
TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_SEQUENCE |
|
||||
MBEDTLS_ASN1_CONSTRUCTED ),
|
||||
0 );
|
||||
TEST_EQUAL( p + len, end );
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
|
||||
goto exit;
|
||||
if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
|
||||
goto exit;
|
||||
TEST_EQUAL( p, end );
|
||||
|
||||
|
||||
TEST_ASSERT( exported_length <=
|
||||
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
|
||||
TEST_ASSERT( exported_length <=
|
||||
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
|
||||
{
|
||||
|
||||
TEST_ASSERT( exported_length <=
|
||||
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
|
||||
TEST_ASSERT( exported_length <=
|
||||
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
|
||||
|
||||
if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
|
||||
{
|
||||
/* The representation of an ECC Montgomery public key is
|
||||
* the raw compressed point */
|
||||
TEST_EQUAL( PSA_BITS_TO_BYTES( bits ), exported_length );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The representation of an ECC Weierstrass public key is:
|
||||
* - 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;
|
||||
* - where m is the bit size associated with the curve.
|
||||
*/
|
||||
TEST_EQUAL( 1 + 2 * PSA_BITS_TO_BYTES( bits ), exported_length );
|
||||
TEST_EQUAL( exported[0], 4 );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
{
|
||||
TEST_ASSERT( ! "Sanity check not implemented for this key type" );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_DES_C)
|
||||
if( type == PSA_KEY_TYPE_DES )
|
||||
{
|
||||
/* Check the parity bits. */
|
||||
unsigned i;
|
||||
for( i = 0; i < bits / 8; i++ )
|
||||
{
|
||||
unsigned bit_count = 0;
|
||||
unsigned m;
|
||||
for( m = 1; m <= 0x100; m <<= 1 )
|
||||
{
|
||||
if( exported[i] & m )
|
||||
++bit_count;
|
||||
}
|
||||
TEST_ASSERT( bit_count % 2 != 0 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exercise_export_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage )
|
||||
{
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
uint8_t *exported = NULL;
|
||||
size_t exported_size = 0;
|
||||
size_t exported_length = 0;
|
||||
int ok = 0;
|
||||
|
||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||
|
||||
exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
|
||||
psa_get_key_type( &attributes ),
|
||||
psa_get_key_bits( &attributes ) );
|
||||
ASSERT_ALLOC( exported, exported_size );
|
||||
|
||||
if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
|
||||
! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
|
||||
{
|
||||
TEST_EQUAL( psa_export_key( key, exported,
|
||||
exported_size, &exported_length ),
|
||||
PSA_ERROR_NOT_PERMITTED );
|
||||
ok = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
PSA_ASSERT( psa_export_key( key,
|
||||
exported, exported_size,
|
||||
&exported_length ) );
|
||||
ok = mbedtls_test_psa_exported_key_sanity_check(
|
||||
psa_get_key_type( &attributes ), psa_get_key_bits( &attributes ),
|
||||
exported, exported_length );
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Key attributes may have been returned by psa_get_key_attributes()
|
||||
* thus reset them as required.
|
||||
*/
|
||||
psa_reset_key_attributes( &attributes );
|
||||
|
||||
mbedtls_free( exported );
|
||||
return( ok );
|
||||
}
|
||||
|
||||
static int exercise_export_public_key( mbedtls_svc_key_id_t key )
|
||||
{
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_type_t public_type;
|
||||
uint8_t *exported = NULL;
|
||||
size_t exported_size = 0;
|
||||
size_t exported_length = 0;
|
||||
int ok = 0;
|
||||
|
||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||
if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
|
||||
{
|
||||
exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
|
||||
psa_get_key_type( &attributes ),
|
||||
psa_get_key_bits( &attributes ) );
|
||||
ASSERT_ALLOC( exported, exported_size );
|
||||
|
||||
TEST_EQUAL( psa_export_public_key( key, exported,
|
||||
exported_size, &exported_length ),
|
||||
PSA_ERROR_INVALID_ARGUMENT );
|
||||
ok = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
|
||||
psa_get_key_type( &attributes ) );
|
||||
exported_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_type,
|
||||
psa_get_key_bits( &attributes ) );
|
||||
ASSERT_ALLOC( exported, exported_size );
|
||||
|
||||
PSA_ASSERT( psa_export_public_key( key,
|
||||
exported, exported_size,
|
||||
&exported_length ) );
|
||||
ok = mbedtls_test_psa_exported_key_sanity_check(
|
||||
public_type, psa_get_key_bits( &attributes ),
|
||||
exported, exported_length );
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Key attributes may have been returned by psa_get_key_attributes()
|
||||
* thus reset them as required.
|
||||
*/
|
||||
psa_reset_key_attributes( &attributes );
|
||||
|
||||
mbedtls_free( exported );
|
||||
return( ok );
|
||||
}
|
||||
|
||||
int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
int ok = 0;
|
||||
|
||||
if( ! check_key_attributes_sanity( key ) )
|
||||
return( 0 );
|
||||
|
||||
if( alg == 0 )
|
||||
ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
|
||||
else if( PSA_ALG_IS_MAC( alg ) )
|
||||
ok = exercise_mac_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_CIPHER( alg ) )
|
||||
ok = exercise_cipher_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_AEAD( alg ) )
|
||||
ok = exercise_aead_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_SIGN( alg ) )
|
||||
ok = exercise_signature_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
|
||||
ok = exercise_asymmetric_encryption_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
|
||||
ok = exercise_key_derivation_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
|
||||
ok = exercise_raw_key_agreement_key( key, usage, alg );
|
||||
else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
|
||||
ok = exercise_key_agreement_key( key, usage, alg );
|
||||
else
|
||||
TEST_ASSERT( ! "No code to exercise this category of algorithm" );
|
||||
|
||||
ok = ok && exercise_export_key( key, usage );
|
||||
ok = ok && exercise_export_public_key( key );
|
||||
|
||||
exit:
|
||||
return( ok );
|
||||
}
|
||||
|
||||
psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
|
||||
psa_algorithm_t alg )
|
||||
{
|
||||
if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
|
||||
{
|
||||
return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
|
||||
PSA_KEY_USAGE_VERIFY_HASH :
|
||||
PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
|
||||
}
|
||||
else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
|
||||
PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
|
||||
{
|
||||
return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
|
||||
PSA_KEY_USAGE_ENCRYPT :
|
||||
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
|
||||
}
|
||||
else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
|
||||
PSA_ALG_IS_KEY_AGREEMENT( alg ) )
|
||||
{
|
||||
return( PSA_KEY_USAGE_DERIVE );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_C */
|
||||
223
tests/src/threading_helpers.c
Normal file
223
tests/src/threading_helpers.c
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/** Mutex usage verification framework. */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <test/helpers.h>
|
||||
#include <test/macros.h>
|
||||
|
||||
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
|
||||
|
||||
#include "mbedtls/threading.h"
|
||||
|
||||
/** Mutex usage verification framework.
|
||||
*
|
||||
* The mutex usage verification code below aims to detect bad usage of
|
||||
* Mbed TLS's mutex abstraction layer at runtime. Note that this is solely
|
||||
* about the use of the mutex itself, not about checking whether the mutex
|
||||
* correctly protects whatever it is supposed to protect.
|
||||
*
|
||||
* The normal usage of a mutex is:
|
||||
* ```
|
||||
* digraph mutex_states {
|
||||
* "UNINITIALIZED"; // the initial state
|
||||
* "IDLE";
|
||||
* "FREED";
|
||||
* "LOCKED";
|
||||
* "UNINITIALIZED" -> "IDLE" [label="init"];
|
||||
* "FREED" -> "IDLE" [label="init"];
|
||||
* "IDLE" -> "LOCKED" [label="lock"];
|
||||
* "LOCKED" -> "IDLE" [label="unlock"];
|
||||
* "IDLE" -> "FREED" [label="free"];
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* All bad transitions that can be unambiguously detected are reported.
|
||||
* An attempt to use an uninitialized mutex cannot be detected in general
|
||||
* since the memory content may happen to denote a valid state. For the same
|
||||
* reason, a double init cannot be detected.
|
||||
* All-bits-zero is the state of a freed mutex, which is distinct from an
|
||||
* initialized mutex, so attempting to use zero-initialized memory as a mutex
|
||||
* without calling the init function is detected.
|
||||
*
|
||||
* The framework attempts to detect missing calls to init and free by counting
|
||||
* calls to init and free. If there are more calls to init than free, this
|
||||
* means that a mutex is not being freed somewhere, which is a memory leak
|
||||
* on platforms where a mutex consumes resources other than the
|
||||
* mbedtls_threading_mutex_t object itself. If there are more calls to free
|
||||
* than init, this indicates a missing init, which is likely to be detected
|
||||
* by an attempt to lock the mutex as well. A limitation of this framework is
|
||||
* that it cannot detect scenarios where there is exactly the same number of
|
||||
* calls to init and free but the calls don't match. A bug like this is
|
||||
* unlikely to happen uniformly throughout the whole test suite though.
|
||||
*
|
||||
* If an error is detected, this framework will report what happened and the
|
||||
* test case will be marked as failed. Unfortunately, the error report cannot
|
||||
* indicate the exact location of the problematic call. To locate the error,
|
||||
* use a debugger and set a breakpoint on mbedtls_test_mutex_usage_error().
|
||||
*/
|
||||
enum value_of_mutex_is_valid_field
|
||||
{
|
||||
/* Potential values for the is_valid field of mbedtls_threading_mutex_t.
|
||||
* Note that MUTEX_FREED must be 0 and MUTEX_IDLE must be 1 for
|
||||
* compatibility with threading_mutex_init_pthread() and
|
||||
* threading_mutex_free_pthread(). MUTEX_LOCKED could be any nonzero
|
||||
* value. */
|
||||
MUTEX_FREED = 0, //!< Set by threading_mutex_free_pthread
|
||||
MUTEX_IDLE = 1, //!< Set by threading_mutex_init_pthread and by our unlock
|
||||
MUTEX_LOCKED = 2, //!< Set by our lock
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*init)( mbedtls_threading_mutex_t * );
|
||||
void (*free)( mbedtls_threading_mutex_t * );
|
||||
int (*lock)( mbedtls_threading_mutex_t * );
|
||||
int (*unlock)( mbedtls_threading_mutex_t * );
|
||||
} mutex_functions_t;
|
||||
static mutex_functions_t mutex_functions;
|
||||
|
||||
/** The total number of calls to mbedtls_mutex_init(), minus the total number
|
||||
* of calls to mbedtls_mutex_free().
|
||||
*
|
||||
* Reset to 0 after each test case.
|
||||
*/
|
||||
static int live_mutexes;
|
||||
|
||||
static void mbedtls_test_mutex_usage_error( mbedtls_threading_mutex_t *mutex,
|
||||
const char *msg )
|
||||
{
|
||||
(void) mutex;
|
||||
if( mbedtls_test_info.mutex_usage_error == NULL )
|
||||
mbedtls_test_info.mutex_usage_error = msg;
|
||||
mbedtls_fprintf( stdout, "[mutex: %s] ", msg );
|
||||
/* Don't mark the test as failed yet. This way, if the test fails later
|
||||
* for a functional reason, the test framework will report the message
|
||||
* and location for this functional reason. If the test passes,
|
||||
* mbedtls_test_mutex_usage_check() will mark it as failed. */
|
||||
}
|
||||
|
||||
static void mbedtls_test_wrap_mutex_init( mbedtls_threading_mutex_t *mutex )
|
||||
{
|
||||
mutex_functions.init( mutex );
|
||||
if( mutex->is_valid )
|
||||
++live_mutexes;
|
||||
}
|
||||
|
||||
static void mbedtls_test_wrap_mutex_free( mbedtls_threading_mutex_t *mutex )
|
||||
{
|
||||
switch( mutex->is_valid )
|
||||
{
|
||||
case MUTEX_FREED:
|
||||
mbedtls_test_mutex_usage_error( mutex, "free without init or double free" );
|
||||
break;
|
||||
case MUTEX_IDLE:
|
||||
/* Do nothing. The underlying free function will reset is_valid
|
||||
* to 0. */
|
||||
break;
|
||||
case MUTEX_LOCKED:
|
||||
mbedtls_test_mutex_usage_error( mutex, "free without unlock" );
|
||||
break;
|
||||
default:
|
||||
mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
|
||||
break;
|
||||
}
|
||||
if( mutex->is_valid )
|
||||
--live_mutexes;
|
||||
mutex_functions.free( mutex );
|
||||
}
|
||||
|
||||
static int mbedtls_test_wrap_mutex_lock( mbedtls_threading_mutex_t *mutex )
|
||||
{
|
||||
int ret = mutex_functions.lock( mutex );
|
||||
switch( mutex->is_valid )
|
||||
{
|
||||
case MUTEX_FREED:
|
||||
mbedtls_test_mutex_usage_error( mutex, "lock without init" );
|
||||
break;
|
||||
case MUTEX_IDLE:
|
||||
if( ret == 0 )
|
||||
mutex->is_valid = 2;
|
||||
break;
|
||||
case MUTEX_LOCKED:
|
||||
mbedtls_test_mutex_usage_error( mutex, "double lock" );
|
||||
break;
|
||||
default:
|
||||
mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
|
||||
break;
|
||||
}
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int mbedtls_test_wrap_mutex_unlock( mbedtls_threading_mutex_t *mutex )
|
||||
{
|
||||
int ret = mutex_functions.unlock( mutex );
|
||||
switch( mutex->is_valid )
|
||||
{
|
||||
case MUTEX_FREED:
|
||||
mbedtls_test_mutex_usage_error( mutex, "unlock without init" );
|
||||
break;
|
||||
case MUTEX_IDLE:
|
||||
mbedtls_test_mutex_usage_error( mutex, "unlock without lock" );
|
||||
break;
|
||||
case MUTEX_LOCKED:
|
||||
if( ret == 0 )
|
||||
mutex->is_valid = MUTEX_IDLE;
|
||||
break;
|
||||
default:
|
||||
mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
|
||||
break;
|
||||
}
|
||||
return( ret );
|
||||
}
|
||||
|
||||
void mbedtls_test_mutex_usage_init( void )
|
||||
{
|
||||
mutex_functions.init = mbedtls_mutex_init;
|
||||
mutex_functions.free = mbedtls_mutex_free;
|
||||
mutex_functions.lock = mbedtls_mutex_lock;
|
||||
mutex_functions.unlock = mbedtls_mutex_unlock;
|
||||
mbedtls_mutex_init = &mbedtls_test_wrap_mutex_init;
|
||||
mbedtls_mutex_free = &mbedtls_test_wrap_mutex_free;
|
||||
mbedtls_mutex_lock = &mbedtls_test_wrap_mutex_lock;
|
||||
mbedtls_mutex_unlock = &mbedtls_test_wrap_mutex_unlock;
|
||||
}
|
||||
|
||||
void mbedtls_test_mutex_usage_check( void )
|
||||
{
|
||||
if( live_mutexes != 0 )
|
||||
{
|
||||
/* A positive number (more init than free) means that a mutex resource
|
||||
* is leaking (on platforms where a mutex consumes more than the
|
||||
* mbedtls_threading_mutex_t object itself). The rare case of a
|
||||
* negative number means a missing init somewhere. */
|
||||
mbedtls_fprintf( stdout, "[mutex: %d leaked] ", live_mutexes );
|
||||
live_mutexes = 0;
|
||||
if( mbedtls_test_info.mutex_usage_error == NULL )
|
||||
mbedtls_test_info.mutex_usage_error = "missing free";
|
||||
}
|
||||
if( mbedtls_test_info.mutex_usage_error != NULL &&
|
||||
mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED )
|
||||
{
|
||||
/* Functionally, the test passed. But there was a mutex usage error,
|
||||
* so mark the test as failed after all. */
|
||||
mbedtls_test_fail( "Mutex usage error", __LINE__, __FILE__ );
|
||||
}
|
||||
mbedtls_test_info.mutex_usage_error = NULL;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_TEST_MUTEX_USAGE */
|
||||
Loading…
Add table
Add a link
Reference in a new issue