Add test class for key generation

Genertae test_suite_psa_crypto_generate_key.generated.data.
Use test_suite_psa_crypto_generate_key.function as a test function.

Signed-off-by: Przemyslaw Stekiel <przemyslaw.stekiel@mobica.com>
diff --git a/scripts/mbedtls_dev/test_case.py b/scripts/mbedtls_dev/test_case.py
index d01e143..11117fc 100644
--- a/scripts/mbedtls_dev/test_case.py
+++ b/scripts/mbedtls_dev/test_case.py
@@ -42,6 +42,7 @@
         self.dependencies = [] #type: List[str]
         self.function = None #type: Optional[str]
         self.arguments = [] #type: List[str]
+        self.result = '' #type: str
 
     def add_comment(self, *lines: str) -> None:
         self.comments += lines
@@ -58,6 +59,9 @@
     def set_arguments(self, arguments: List[str]) -> None:
         self.arguments = arguments
 
+    def set_result(self, result: str) -> None:
+        self.result = result
+
     def check_completeness(self) -> None:
         if self.description is None:
             raise MissingDescription
@@ -81,9 +85,11 @@
         out.write(self.description + '\n')
         if self.dependencies:
             out.write('depends_on:' + ':'.join(self.dependencies) + '\n')
-        out.write(self.function + ':' + ':'.join(self.arguments) + '\n')
-
-
+        out.write(self.function + ':' + ':'.join(self.arguments))
+        if self.result:
+            out.write(':' + self.result + '\n')
+        else:
+            out.write('\n')
 
 def write_data_file(filename: str,
                     test_cases: Iterable[TestCase],
diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py
index 4c8143f..b4a13ba 100755
--- a/tests/scripts/generate_psa_tests.py
+++ b/tests/scripts/generate_psa_tests.py
@@ -261,6 +261,83 @@
                 yield from self.test_cases_for_key_type_not_supported(
                     kt, 0, param_descr='curve')
 
+def test_case_for_key_generation(
+        key_type: str, bits: int,
+        dependencies: List[str],
+        *args: str,
+        result: str = '',
+        param_descr: 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))
+    tc.set_result(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
+
+    def test_cases_for_key_type_key_generation(
+            self,
+            kt: crypto_knowledge.KeyType,
+            param: Optional[int] = None,
+            param_descr: str = '',
+    ) -> 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'):
+            generate_dependencies = []
+            result = 'PSA_ERROR_INVALID_ARGUMENT'
+        else:
+            generate_dependencies = import_dependencies
+        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,
+                param_descr=param_descr
+            )
+
+    ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
+                     'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
+
+    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, param_descr='type')
+                yield from self.test_cases_for_key_type_key_generation(
+                    kt, 0, param_descr='curve')
+
+
 class StorageKey(psa_storage.Key):
     """Representation of a key for storage format testing."""
 
@@ -682,6 +759,8 @@
         test_case.write_data_file(filename, test_cases)
 
     TARGETS = {
+        'test_suite_psa_crypto_generate_key.generated':
+        lambda info: KeyGenerate(info).test_cases_for_key_generation(),
         'test_suite_psa_crypto_not_supported.generated':
         lambda info: NotSupported(info).test_cases_for_not_supported(),
         'test_suite_psa_crypto_storage_format.current':
diff --git a/tests/suites/test_suite_psa_crypto_generate_key.function b/tests/suites/test_suite_psa_crypto_generate_key.function
new file mode 100644
index 0000000..7404d38
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_generate_key.function
@@ -0,0 +1,54 @@
+/* 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, int bits, int result)
+{
+    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_lifetime_t _key_life_time = (psa_key_lifetime_t) 0;
+    psa_key_usage_t _key_usage_flags = (psa_key_usage_t) 0;
+    psa_algorithm_t _key_algorithm = (psa_algorithm_t) 0;
+    psa_key_type_t _key_type = (psa_key_type_t) key_type;
+    size_t _key_bits = (size_t) bits;
+    psa_status_t _result = (psa_status_t) result;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_lifetime( &attributes, _key_life_time );
+    psa_set_key_usage_flags( &attributes, _key_usage_flags );
+    psa_set_key_algorithm( &attributes, _key_algorithm );
+    psa_set_key_type( &attributes, _key_type );
+    psa_set_key_bits( &attributes, _key_bits );
+    TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
+                _result );
+
+    // Verify attributes of the created key on success
+    if (_result == PSA_SUCCESS)
+    {
+        psa_key_attributes_t key_attributes = {0};
+        PSA_ASSERT( psa_get_key_attributes( key_id, &key_attributes ) );
+        TEST_EQUAL( psa_get_key_lifetime( &key_attributes ), 0 );
+        TEST_EQUAL( psa_get_key_usage_flags( &key_attributes ), 0 );
+        TEST_EQUAL( psa_get_key_algorithm( &key_attributes ), 0 );
+        TEST_EQUAL( psa_get_key_type( &key_attributes ), _key_type );
+        TEST_EQUAL( psa_get_key_bits( &key_attributes ), _key_bits );
+    }
+
+exit:
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */