mirror of
				https://github.com/cuberite/polarssl.git
				synced 2025-10-30 19:20:40 -04:00 
			
		
		
		
	Merge pull request #5092 from mprse/generate_key2
Generate test cases for PSA key generation
This commit is contained in:
		
						commit
						f1a7ea88d1
					
				| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gilles Peskine
						Gilles Peskine