Merge pull request #5092 from mprse/generate_key2
Generate test cases for PSA key generation
This commit is contained in:
commit
f1a7ea88d1
4 changed files with 131 additions and 57 deletions
|
@ -83,8 +83,6 @@ class TestCase:
|
||||||
out.write('depends_on:' + ':'.join(self.dependencies) + '\n')
|
out.write('depends_on:' + ':'.join(self.dependencies) + '\n')
|
||||||
out.write(self.function + ':' + ':'.join(self.arguments) + '\n')
|
out.write(self.function + ':' + ':'.join(self.arguments) + '\n')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def write_data_file(filename: str,
|
def write_data_file(filename: str,
|
||||||
test_cases: Iterable[TestCase],
|
test_cases: Iterable[TestCase],
|
||||||
caller: Optional[str] = None) -> None:
|
caller: Optional[str] = None) -> None:
|
||||||
|
|
|
@ -96,7 +96,7 @@ def hack_dependencies_not_implemented(dependencies: List[str]) -> None:
|
||||||
if _implemented_dependencies is None:
|
if _implemented_dependencies is None:
|
||||||
_implemented_dependencies = \
|
_implemented_dependencies = \
|
||||||
read_implemented_dependencies('include/psa/crypto_config.h')
|
read_implemented_dependencies('include/psa/crypto_config.h')
|
||||||
if not all(dep.lstrip('!') in _implemented_dependencies
|
if not all((dep.lstrip('!') in _implemented_dependencies or 'PSA_WANT' not in dep)
|
||||||
for dep in dependencies):
|
for dep in dependencies):
|
||||||
dependencies.append('DEPENDENCY_NOT_IMPLEMENTED_YET')
|
dependencies.append('DEPENDENCY_NOT_IMPLEMENTED_YET')
|
||||||
|
|
||||||
|
@ -155,30 +155,8 @@ def test_case_for_key_type_not_supported(
|
||||||
tc.set_arguments([key_type] + list(args))
|
tc.set_arguments([key_type] + list(args))
|
||||||
return tc
|
return tc
|
||||||
|
|
||||||
def test_case_for_key_type_invalid_argument(
|
|
||||||
verb: str, key_type: str, bits: int,
|
|
||||||
dependencies: List[str],
|
|
||||||
*args: str,
|
|
||||||
param_descr: str = ''
|
|
||||||
) -> test_case.TestCase:
|
|
||||||
"""Return one test case exercising a key creation method
|
|
||||||
for an invalid argument when key is public.
|
|
||||||
"""
|
|
||||||
hack_dependencies_not_implemented(dependencies)
|
|
||||||
tc = test_case.TestCase()
|
|
||||||
short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
|
|
||||||
adverb = 'not' if dependencies else 'never'
|
|
||||||
if param_descr:
|
|
||||||
adverb = param_descr + ' ' + adverb
|
|
||||||
tc.set_description('PSA {} {} {}-bit invalid argument'
|
|
||||||
.format(verb, short_key_type, bits))
|
|
||||||
tc.set_function(verb + '_invalid_argument')
|
|
||||||
tc.set_dependencies(dependencies)
|
|
||||||
tc.set_arguments([key_type] + list(args))
|
|
||||||
return tc
|
|
||||||
|
|
||||||
class NotSupported:
|
class NotSupported:
|
||||||
"""Generate test cases for when something is not supported or argument is inavlid."""
|
"""Generate test cases for when something is not supported."""
|
||||||
|
|
||||||
def __init__(self, info: Information) -> None:
|
def __init__(self, info: Information) -> None:
|
||||||
self.constructors = info.constructors
|
self.constructors = info.constructors
|
||||||
|
@ -193,13 +171,11 @@ class NotSupported:
|
||||||
param: Optional[int] = None,
|
param: Optional[int] = None,
|
||||||
param_descr: str = '',
|
param_descr: str = '',
|
||||||
) -> Iterator[test_case.TestCase]:
|
) -> Iterator[test_case.TestCase]:
|
||||||
"""Return test cases exercising key creation when the given type is unsupported
|
"""Return test cases exercising key creation when the given type is unsupported.
|
||||||
or argument is invalid.
|
|
||||||
|
|
||||||
If param is present and not None, emit test cases conditioned on this
|
If param is present and not None, emit test cases conditioned on this
|
||||||
parameter not being supported. If it is absent or None, emit test cases
|
parameter not being supported. If it is absent or None, emit test cases
|
||||||
conditioned on the base type not being supported. If key is public emit test
|
conditioned on the base type not being supported.
|
||||||
case for invalid argument.
|
|
||||||
"""
|
"""
|
||||||
if kt.name in self.ALWAYS_SUPPORTED:
|
if kt.name in self.ALWAYS_SUPPORTED:
|
||||||
# Don't generate test cases for key types that are always supported.
|
# Don't generate test cases for key types that are always supported.
|
||||||
|
@ -227,14 +203,9 @@ class NotSupported:
|
||||||
# supported or not depending on implementation capabilities,
|
# supported or not depending on implementation capabilities,
|
||||||
# only generate the test case once.
|
# only generate the test case once.
|
||||||
continue
|
continue
|
||||||
if kt.name.endswith('_PUBLIC_KEY'):
|
# For public key we expect that key generation fails with
|
||||||
yield test_case_for_key_type_invalid_argument(
|
# INVALID_ARGUMENT. It is handled by KeyGenerate class.
|
||||||
'generate', kt.expression, bits,
|
if not kt.name.endswith('_PUBLIC_KEY'):
|
||||||
finish_family_dependencies(generate_dependencies, bits),
|
|
||||||
str(bits),
|
|
||||||
param_descr=param_descr,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
yield test_case_for_key_type_not_supported(
|
yield test_case_for_key_type_not_supported(
|
||||||
'generate', kt.expression, bits,
|
'generate', kt.expression, bits,
|
||||||
finish_family_dependencies(generate_dependencies, bits),
|
finish_family_dependencies(generate_dependencies, bits),
|
||||||
|
@ -261,6 +232,79 @@ class NotSupported:
|
||||||
yield from self.test_cases_for_key_type_not_supported(
|
yield from self.test_cases_for_key_type_not_supported(
|
||||||
kt, 0, param_descr='curve')
|
kt, 0, param_descr='curve')
|
||||||
|
|
||||||
|
def test_case_for_key_generation(
|
||||||
|
key_type: str, bits: int,
|
||||||
|
dependencies: List[str],
|
||||||
|
*args: str,
|
||||||
|
result: str = ''
|
||||||
|
) -> test_case.TestCase:
|
||||||
|
"""Return one test case exercising a key generation.
|
||||||
|
"""
|
||||||
|
hack_dependencies_not_implemented(dependencies)
|
||||||
|
tc = test_case.TestCase()
|
||||||
|
short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
|
||||||
|
tc.set_description('PSA {} {}-bit'
|
||||||
|
.format(short_key_type, bits))
|
||||||
|
tc.set_dependencies(dependencies)
|
||||||
|
tc.set_function('generate_key')
|
||||||
|
tc.set_arguments([key_type] + list(args) + [result])
|
||||||
|
|
||||||
|
return tc
|
||||||
|
|
||||||
|
class KeyGenerate:
|
||||||
|
"""Generate positive and negative (invalid argument) test cases for key generation."""
|
||||||
|
|
||||||
|
def __init__(self, info: Information) -> None:
|
||||||
|
self.constructors = info.constructors
|
||||||
|
|
||||||
|
ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
|
||||||
|
'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def test_cases_for_key_type_key_generation(
|
||||||
|
kt: crypto_knowledge.KeyType
|
||||||
|
) -> Iterator[test_case.TestCase]:
|
||||||
|
"""Return test cases exercising key generation.
|
||||||
|
|
||||||
|
All key types can be generated except for public keys. For public key
|
||||||
|
PSA_ERROR_INVALID_ARGUMENT status is expected.
|
||||||
|
"""
|
||||||
|
result = 'PSA_SUCCESS'
|
||||||
|
|
||||||
|
import_dependencies = [psa_want_symbol(kt.name)]
|
||||||
|
if kt.params is not None:
|
||||||
|
import_dependencies += [psa_want_symbol(sym)
|
||||||
|
for i, sym in enumerate(kt.params)]
|
||||||
|
if kt.name.endswith('_PUBLIC_KEY'):
|
||||||
|
# The library checks whether the key type is a public key generically,
|
||||||
|
# before it reaches a point where it needs support for the specific key
|
||||||
|
# type, so it returns INVALID_ARGUMENT for unsupported public key types.
|
||||||
|
generate_dependencies = []
|
||||||
|
result = 'PSA_ERROR_INVALID_ARGUMENT'
|
||||||
|
else:
|
||||||
|
generate_dependencies = import_dependencies
|
||||||
|
if kt.name == 'PSA_KEY_TYPE_RSA_KEY_PAIR':
|
||||||
|
generate_dependencies.append("MBEDTLS_GENPRIME")
|
||||||
|
for bits in kt.sizes_to_test():
|
||||||
|
yield test_case_for_key_generation(
|
||||||
|
kt.expression, bits,
|
||||||
|
finish_family_dependencies(generate_dependencies, bits),
|
||||||
|
str(bits),
|
||||||
|
result
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_cases_for_key_generation(self) -> Iterator[test_case.TestCase]:
|
||||||
|
"""Generate test cases that exercise the generation of keys."""
|
||||||
|
for key_type in sorted(self.constructors.key_types):
|
||||||
|
if key_type in self.ECC_KEY_TYPES:
|
||||||
|
continue
|
||||||
|
kt = crypto_knowledge.KeyType(key_type)
|
||||||
|
yield from self.test_cases_for_key_type_key_generation(kt)
|
||||||
|
for curve_family in sorted(self.constructors.ecc_curves):
|
||||||
|
for constr in self.ECC_KEY_TYPES:
|
||||||
|
kt = crypto_knowledge.KeyType(constr, [curve_family])
|
||||||
|
yield from self.test_cases_for_key_type_key_generation(kt)
|
||||||
|
|
||||||
class StorageKey(psa_storage.Key):
|
class StorageKey(psa_storage.Key):
|
||||||
"""Representation of a key for storage format testing."""
|
"""Representation of a key for storage format testing."""
|
||||||
|
|
||||||
|
@ -682,6 +726,8 @@ class TestGenerator:
|
||||||
test_case.write_data_file(filename, test_cases)
|
test_case.write_data_file(filename, test_cases)
|
||||||
|
|
||||||
TARGETS = {
|
TARGETS = {
|
||||||
|
'test_suite_psa_crypto_generate_key.generated':
|
||||||
|
lambda info: KeyGenerate(info).test_cases_for_key_generation(),
|
||||||
'test_suite_psa_crypto_not_supported.generated':
|
'test_suite_psa_crypto_not_supported.generated':
|
||||||
lambda info: NotSupported(info).test_cases_for_not_supported(),
|
lambda info: NotSupported(info).test_cases_for_not_supported(),
|
||||||
'test_suite_psa_crypto_storage_format.current':
|
'test_suite_psa_crypto_storage_format.current':
|
||||||
|
|
49
tests/suites/test_suite_psa_crypto_generate_key.function
Normal file
49
tests/suites/test_suite_psa_crypto_generate_key.function
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* BEGIN_HEADER */
|
||||||
|
|
||||||
|
#include "psa/crypto.h"
|
||||||
|
#include "test/psa_crypto_helpers.h"
|
||||||
|
|
||||||
|
#define INVALID_KEY_ID mbedtls_svc_key_id_make( 0, 0xfedcba98 )
|
||||||
|
|
||||||
|
/* END_HEADER */
|
||||||
|
|
||||||
|
/* BEGIN_DEPENDENCIES
|
||||||
|
* depends_on:MBEDTLS_PSA_CRYPTO_C
|
||||||
|
* END_DEPENDENCIES
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* BEGIN_CASE */
|
||||||
|
void generate_key( int key_type_arg, int bits_arg, int expected_status_arg)
|
||||||
|
{
|
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
|
||||||
|
|
||||||
|
// key lifetiem, usage flags, algorithm are irrelevant for this test
|
||||||
|
psa_key_type_t key_type = key_type_arg;
|
||||||
|
size_t bits = bits_arg;
|
||||||
|
psa_status_t expected_status = expected_status_arg;
|
||||||
|
|
||||||
|
PSA_ASSERT( psa_crypto_init( ) );
|
||||||
|
psa_set_key_type( &attributes, key_type );
|
||||||
|
psa_set_key_bits( &attributes, bits );
|
||||||
|
TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
|
||||||
|
expected_status );
|
||||||
|
|
||||||
|
// Verify attributes of the created key on success
|
||||||
|
if ( expected_status == PSA_SUCCESS )
|
||||||
|
{
|
||||||
|
psa_reset_key_attributes(&attributes);
|
||||||
|
PSA_ASSERT( psa_get_key_attributes( key_id, &attributes ) );
|
||||||
|
TEST_EQUAL( psa_get_key_lifetime( &attributes ), PSA_KEY_LIFETIME_VOLATILE );
|
||||||
|
TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
|
||||||
|
TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
|
||||||
|
TEST_EQUAL( psa_get_key_type( &attributes ), key_type );
|
||||||
|
TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
psa_reset_key_attributes(&attributes);
|
||||||
|
psa_destroy_key( key_id );
|
||||||
|
PSA_DONE( );
|
||||||
|
}
|
||||||
|
/* END_CASE */
|
|
@ -50,22 +50,3 @@ exit:
|
||||||
PSA_DONE( );
|
PSA_DONE( );
|
||||||
}
|
}
|
||||||
/* END_CASE */
|
/* END_CASE */
|
||||||
|
|
||||||
/* BEGIN_CASE */
|
|
||||||
void generate_invalid_argument( int key_type, int bits )
|
|
||||||
{
|
|
||||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
||||||
mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
|
|
||||||
|
|
||||||
PSA_ASSERT( psa_crypto_init( ) );
|
|
||||||
psa_set_key_type( &attributes, key_type );
|
|
||||||
psa_set_key_bits( &attributes, bits );
|
|
||||||
TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
|
|
||||||
PSA_ERROR_INVALID_ARGUMENT );
|
|
||||||
TEST_ASSERT( mbedtls_svc_key_id_equal( key_id, MBEDTLS_SVC_KEY_ID_INIT ) );
|
|
||||||
|
|
||||||
exit:
|
|
||||||
psa_destroy_key( key_id );
|
|
||||||
PSA_DONE( );
|
|
||||||
}
|
|
||||||
/* END_CASE */
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue