generate_test_keys: generate also look-up table in script

Remove static declaration of look-up table from test_suite_pk
and generate it automatically with Python.

Signed-off-by: Valerio Setti <valerio.setti@nordicsemi.no>
diff --git a/tests/scripts/generate_test_keys.py b/tests/scripts/generate_test_keys.py
index 75e85ce..9c5786d 100755
--- a/tests/scripts/generate_test_keys.py
+++ b/tests/scripts/generate_test_keys.py
@@ -32,13 +32,6 @@
 def convert_der_to_c(array_name: str, key_data: bytes) -> str:
     return ''.join(c_byte_array_literal_content(array_name, key_data))
 
-EC_NAME_CONVERSION = {
-    'PSA_ECC_FAMILY_SECP_K1': ['secp', 'k1'],
-    'PSA_ECC_FAMILY_SECP_R1': ['secp', 'r1'],
-    'PSA_ECC_FAMILY_BRAINPOOL_P_R1': ['bp', 'r1'],
-    'PSA_ECC_FAMILY_MONTGOMERY': ['curve', ''],
-}
-
 def get_key_type(key: str) -> str:
     if re.match('PSA_KEY_TYPE_RSA_.*', key):
         return "rsa"
@@ -54,11 +47,49 @@
         raise Exception("Unable to get EC family from {}".format(key))
     return match.group(1)
 
-def get_key_role(key_type: str) -> str:
-    if re.match('PSA_KEY_TYPE_.*_KEY_PAIR', key_type):
-        return "priv"
-    else:
-        return "pub"
+# Legacy EC group ID do not support all the key types that PSA does, so the
+# following dictionaries are used for:
+# - getting prefix/suffix for legacy curve names
+# - understand if the curve is supported in legacy symbols (MBEDTLS_ECP_DP_...)
+EC_NAME_CONVERSION = {
+    'PSA_ECC_FAMILY_SECP_K1': {
+        192: ['secp', 'k1'],
+        224: ['secp', 'k1'],
+        256: ['secp', 'k1']
+    },
+    'PSA_ECC_FAMILY_SECP_R1': {
+        192: ['secp', 'r1'],
+        224: ['secp', 'r1'],
+        256: ['secp', 'r1'],
+        384: ['secp', 'r1'],
+        521: ['secp', 'r1']
+    },
+    'PSA_ECC_FAMILY_BRAINPOOL_P_R1': {
+        256: ['bp', 'r1'],
+        384: ['bp', 'r1'],
+        512: ['bp', 'r1']
+    },
+    'PSA_ECC_FAMILY_MONTGOMERY': {
+        255: ['curve', '19'],
+        448: ['curve', '']
+    }
+}
+
+def get_ec_curve_name(priv_key: str, bits: int) -> str:
+    ec_family = get_ec_key_family(priv_key)
+    try:
+        prefix = EC_NAME_CONVERSION[ec_family][bits][0]
+        suffix = EC_NAME_CONVERSION[ec_family][bits][1]
+    except: # pylint: disable=bare-except
+        return ""
+    return prefix + str(bits) + suffix
+
+def get_look_up_table_entry(key_type: str, curve_or_keybits: str,
+                            priv_array_name: str, pub_array_name: str) -> Iterator[str]:
+    yield "\n    {{ {}, ".format("1" if key_type == "ec" else "0")
+    yield "{},\n".format(curve_or_keybits)
+    yield "      {0}, sizeof({0}),\n".format(priv_array_name)
+    yield "      {0}, sizeof({0}) }},".format(pub_array_name)
 
 def main() -> None:
     # Remove output file if already existing.
@@ -73,33 +104,60 @@
         " *********************************************************************************/\n"
     )
 
-    for key in ASYMMETRIC_KEY_DATA:
-        key_type = get_key_type(key)
+    look_up_table = ""
+
+    # Get a list of private keys only in order to get a single item for every
+    # (key type, key bits) pair. We know that ASYMMETRIC_KEY_DATA
+    # contains also the public counterpart.
+    priv_keys = [key for key in ASYMMETRIC_KEY_DATA if re.match(r'.*_KEY_PAIR', key)]
+
+    for priv_key in priv_keys:
+        key_type = get_key_type(priv_key)
         # Ignore keys which are not EC or RSA
         if key_type == "unknown":
             continue
-        # Ignore undesired EC keys
-        if key_type == "ec":
-            ec_family = get_ec_key_family(key)
-            if not ec_family in EC_NAME_CONVERSION:
-                continue
-        role = get_key_role(key)
 
-        for bits in ASYMMETRIC_KEY_DATA[key]:
+        pub_key = re.sub('_KEY_PAIR', '_PUBLIC_KEY', priv_key)
+
+        for bits in ASYMMETRIC_KEY_DATA[priv_key]:
+            if key_type == "ec":
+                curve = get_ec_curve_name(priv_key, bits)
+                # Ignore EC curves unsupported in legacy symbols
+                if curve == "":
+                    continue
             # Create output array name
             if key_type == "rsa":
-                array_name = "_".join(["test", key_type, str(bits), role])
+                array_name_base = "_".join(["test", key_type, str(bits)])
             else:
-                prefix = EC_NAME_CONVERSION[ec_family][0]
-                suffix = EC_NAME_CONVERSION[ec_family][1]
-                curve = "".join([prefix, str(bits), suffix])
-                array_name = "_".join(["test", key_type, curve, role])
+                array_name_base = "_".join(["test", key_type, curve])
+            array_name_priv = array_name_base + "_priv"
+            array_name_pub = array_name_base + "_pub"
             # Convert bytearray to C array
-            c_array = convert_der_to_c(array_name, ASYMMETRIC_KEY_DATA[key][bits])
+            c_array_priv = convert_der_to_c(array_name_priv, ASYMMETRIC_KEY_DATA[priv_key][bits])
+            c_array_pub = convert_der_to_c(array_name_pub, ASYMMETRIC_KEY_DATA[pub_key][bits])
             # Write the C array to the output file
-            output_file.write("\n")
-            output_file.write(c_array)
-            output_file.write("\n")
+            output_file.write(''.join(["\n", c_array_priv, "\n", c_array_pub, "\n"]))
+            # Update the lookup table
+            if key_type == "ec":
+                curve_or_keybits = "MBEDTLS_ECP_DP_" + curve.upper()
+            else:
+                curve_or_keybits = str(bits)
+            look_up_table = look_up_table + \
+                            ''.join(get_look_up_table_entry(key_type, curve_or_keybits,
+                                                            array_name_priv, array_name_pub))
+    # Write the lookup table: the struct containing pointers to all the arrays we created above.
+    output_file.write("""
+struct predefined_key_element {
+    int is_ec;  // 1 for EC keys; 0 for RSA
+    int curve_or_keybits;
+    const unsigned char *priv_key;
+    size_t priv_key_len;
+    const unsigned char *pub_key;
+    size_t pub_key_len;
+};
+
+struct predefined_key_element predefined_keys[] = {""")
+    output_file.write("{}\n}};\n".format(look_up_table))
 
 if __name__ == '__main__':
     main()