blob: 3c71202d3b75246c1154ea864f665648046e67f7 [file] [log] [blame]
Archana1f1a34a2021-11-17 08:44:07 +05301#!/usr/bin/env python3
Archanae03960e2021-12-19 09:17:04 +05302"""Generate library/psa_crypto_driver_wrappers.c
3
4 This module is invoked by the build sripts to auto generate the
5 psa_crypto_driver_wrappers.c based on template files in
6 script/data_files/driver_templates/.
7"""
8# Copyright The Mbed TLS Contributors
9# SPDX-License-Identifier: Apache-2.0
10#
11# Licensed under the Apache License, Version 2.0 (the "License"); you may
12# not use this file except in compliance with the License.
13# You may obtain a copy of the License at
14#
15# http://www.apache.org/licenses/LICENSE-2.0
16#
17# Unless required by applicable law or agreed to in writing, software
18# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20# See the License for the specific language governing permissions and
21# limitations under the License.
Archana1f1a34a2021-11-17 08:44:07 +053022
23import sys
Archana1f1a34a2021-11-17 08:44:07 +053024import os
Archanae829cd62021-12-24 12:50:36 +053025import json
Archanafdbbcba2022-02-27 05:38:55 +053026from typing import Tuple, NewType
Archanae03960e2021-12-19 09:17:04 +053027import argparse
Archana31438052022-01-09 15:01:20 +053028import jsonschema
Archana1f1a34a2021-11-17 08:44:07 +053029import jinja2
Archanae03960e2021-12-19 09:17:04 +053030from mbedtls_dev import build_tree
Archana1f1a34a2021-11-17 08:44:07 +053031
Archanafdbbcba2022-02-27 05:38:55 +053032JSONSchema = NewType('JSONSchema', object)
Archanaa78dc702022-03-13 17:57:45 +053033# The Driver is an Object, but practically it's indexable and can called a dictionary to
34# keep MyPy happy till MyPy comes with a more composite type for JsonObjects.
35Driver = NewType('Driver', dict)
Archanafdbbcba2022-02-27 05:38:55 +053036
Archanae829cd62021-12-24 12:50:36 +053037def render(template_path: str, driver_jsoncontext: list) -> str:
Archanae03960e2021-12-19 09:17:04 +053038 """
Archanae829cd62021-12-24 12:50:36 +053039 Render template from the input file and driver JSON.
Archanae03960e2021-12-19 09:17:04 +053040 """
Archana6f21e452021-11-23 14:46:51 +053041 environment = jinja2.Environment(
42 loader=jinja2.FileSystemLoader(os.path.dirname(template_path)),
43 keep_trailing_newline=True)
44 template = environment.get_template(os.path.basename(template_path))
Archanae03960e2021-12-19 09:17:04 +053045
Archana31438052022-01-09 15:01:20 +053046 return template.render(drivers=driver_jsoncontext)
Archana1f1a34a2021-11-17 08:44:07 +053047
Archanae829cd62021-12-24 12:50:36 +053048
Archana31438052022-01-09 15:01:20 +053049def generate_driver_wrapper_file(template_dir: str, \
50 output_dir: str, driver_jsoncontext: list) -> None:
Archanae03960e2021-12-19 09:17:04 +053051 """
52 Generate the file psa_crypto_driver_wrapper.c.
53 """
54 driver_wrapper_template_filename = \
Archanae829cd62021-12-24 12:50:36 +053055 os.path.join(template_dir, "psa_crypto_driver_wrappers.c.jinja")
Archana1f1a34a2021-11-17 08:44:07 +053056
Archanae829cd62021-12-24 12:50:36 +053057 result = render(driver_wrapper_template_filename, driver_jsoncontext)
Archana1f1a34a2021-11-17 08:44:07 +053058
Archanae03960e2021-12-19 09:17:04 +053059 with open(os.path.join(output_dir, "psa_crypto_driver_wrappers.c"), 'w') as out_file:
60 out_file.write(result)
Archana6f21e452021-11-23 14:46:51 +053061
Archanae829cd62021-12-24 12:50:36 +053062
Archanafdbbcba2022-02-27 05:38:55 +053063def validate_json(driverjson_data: Driver, driverschema_list: dict) -> bool:
Archanae829cd62021-12-24 12:50:36 +053064 """
Archanafdbbcba2022-02-27 05:38:55 +053065 Validate the Driver JSON against an appropriate schema
66 the schema passed could be that matching an opaque/ transparent driver.
Archana04cfe342022-01-09 13:28:28 +053067 """
Archanafdbbcba2022-02-27 05:38:55 +053068 driver_type = driverjson_data["type"]
69 driver_prefix = driverjson_data["prefix"]
Archana04cfe342022-01-09 13:28:28 +053070 try:
Archanafdbbcba2022-02-27 05:38:55 +053071 _schema = driverschema_list[driver_type]
72 jsonschema.validate(instance=driverjson_data, schema=_schema)
73
74 except KeyError as err:
75 # This could happen if the driverjson_data.type does not exist in the passed in schema list
76 # schemas = {'transparent': transparent_driver_schema, 'opaque': opaque_driver_schema}
77 # Print onto stdout and stderr.
78 print("Unknown Driver type " + driver_type +
79 " for driver " + driver_prefix, str(err))
80 print("Unknown Driver type " + driver_type +
81 " for driver " + driver_prefix, str(err), file=sys.stderr)
82 return False
83
Archana04cfe342022-01-09 13:28:28 +053084 except jsonschema.exceptions.ValidationError as err:
Archanafdbbcba2022-02-27 05:38:55 +053085 # Print onto stdout and stderr.
86 print("Error: Failed to validate data file: {} using schema: {}."
87 "\n Exception Message: \"{}\""
88 " ".format(driverjson_data, _schema, str(err)))
89 print("Error: Failed to validate data file: {} using schema: {}."
90 "\n Exception Message: \"{}\""
91 " ".format(driverjson_data, _schema, str(err)), file=sys.stderr)
Archana04cfe342022-01-09 13:28:28 +053092 return False
93
Archana04cfe342022-01-09 13:28:28 +053094 return True
95
Archanafdbbcba2022-02-27 05:38:55 +053096def read_driver_descriptions(mbedtls_root: str, json_directory: str, \
Archana31438052022-01-09 15:01:20 +053097 jsondriver_list: str) -> Tuple[bool, list]:
Archana04cfe342022-01-09 13:28:28 +053098 """
99 Merge driver JSON files into a single ordered JSON after validation.
Archanae829cd62021-12-24 12:50:36 +0530100 """
Archanafdbbcba2022-02-27 05:38:55 +0530101 result = []
102 with open(os.path.join(mbedtls_root,
103 'scripts',
104 'data_files',
105 'driver_jsons',
106 'driver_transparent_schema.json'), 'r') as file:
Archana04cfe342022-01-09 13:28:28 +0530107 transparent_driver_schema = json.load(file)
Archanafdbbcba2022-02-27 05:38:55 +0530108 with open(os.path.join(mbedtls_root,
109 'scripts',
110 'data_files',
111 'driver_jsons',
112 'driver_opaque_schema.json'), 'r') as file:
Archana04cfe342022-01-09 13:28:28 +0530113 opaque_driver_schema = json.load(file)
114
Archanafdbbcba2022-02-27 05:38:55 +0530115 driver_schema_list = {'transparent':transparent_driver_schema,
116 'opaque':opaque_driver_schema}
117
Archana31438052022-01-09 15:01:20 +0530118 with open(os.path.join(json_directory, jsondriver_list), 'r') as driverlistfile:
Archanae829cd62021-12-24 12:50:36 +0530119 driverlist = json.load(driverlistfile)
120 for file_name in driverlist:
121 with open(os.path.join(json_directory, file_name), 'r') as infile:
Archana04cfe342022-01-09 13:28:28 +0530122 json_data = json.load(infile)
Archanafdbbcba2022-02-27 05:38:55 +0530123 ret = validate_json(json_data, driver_schema_list)
Archana31438052022-01-09 15:01:20 +0530124 if ret is False:
Archana04cfe342022-01-09 13:28:28 +0530125 return ret, []
126 result.append(json_data)
127 return True, result
Archanae829cd62021-12-24 12:50:36 +0530128
129
Archanae03960e2021-12-19 09:17:04 +0530130def main() -> int:
131 """
132 Main with command line arguments.
Archanafdbbcba2022-02-27 05:38:55 +0530133 returns 1 when read_driver_descriptions returns False
Archanae03960e2021-12-19 09:17:04 +0530134 """
Archana4a9e0262021-12-19 13:34:30 +0530135 def_arg_mbedtls_root = build_tree.guess_mbedtls_root()
136 def_arg_output_dir = os.path.join(def_arg_mbedtls_root, 'library')
Archanafdbbcba2022-02-27 05:38:55 +0530137 def_arg_template_dir = os.path.join(def_arg_mbedtls_root,
138 'scripts',
139 'data_files',
140 'driver_templates')
141 def_arg_json_dir = os.path.join(def_arg_mbedtls_root,
142 'scripts',
143 'data_files',
144 'driver_jsons')
Archana4a9e0262021-12-19 13:34:30 +0530145
Archanae03960e2021-12-19 09:17:04 +0530146 parser = argparse.ArgumentParser()
Archana4a9e0262021-12-19 13:34:30 +0530147 parser.add_argument('--mbedtls-root', nargs='?', default=def_arg_mbedtls_root,
Archanae03960e2021-12-19 09:17:04 +0530148 help='root directory of mbedtls source code')
Archanafdbbcba2022-02-27 05:38:55 +0530149 parser.add_argument('--template-dir', nargs='?', default=def_arg_template_dir,
Archanae829cd62021-12-24 12:50:36 +0530150 help='root directory of mbedtls source code')
Archanafdbbcba2022-02-27 05:38:55 +0530151 parser.add_argument('--json-dir', nargs='?', default=def_arg_json_dir,
Archanae829cd62021-12-24 12:50:36 +0530152 help='root directory of mbedtls source code')
Archanafdbbcba2022-02-27 05:38:55 +0530153 parser.add_argument('output-directory', nargs='?',
Archana4a9e0262021-12-19 13:34:30 +0530154 default=def_arg_output_dir, help='output file\'s location')
Archanae03960e2021-12-19 09:17:04 +0530155 args = parser.parse_args()
Archana4a9e0262021-12-19 13:34:30 +0530156
Archana31438052022-01-09 15:01:20 +0530157 mbedtls_root = os.path.abspath(args.mbedtls_root)
Archanafdbbcba2022-02-27 05:38:55 +0530158 output_directory = def_arg_output_dir
159 if args.template_dir is None:
160 args.template_dir = os.path.join(args.mbedtls_root, def_arg_template_dir)
Archanae829cd62021-12-24 12:50:36 +0530161 template_directory = args.template_dir
Archanafdbbcba2022-02-27 05:38:55 +0530162 if args.json_dir is None:
163 args.json_dir = os.path.join(args.mbedtls_root, def_arg_json_dir)
Archana31438052022-01-09 15:01:20 +0530164 json_directory = args.json_dir
Archanae03960e2021-12-19 09:17:04 +0530165
Archanafdbbcba2022-02-27 05:38:55 +0530166 # Read and validate list of driver jsons from driverlist.json
167 ret, merged_driver_json = read_driver_descriptions(mbedtls_root, json_directory,
168 'driverlist.json')
Archana31438052022-01-09 15:01:20 +0530169 if ret is False:
Archanae829cd62021-12-24 12:50:36 +0530170 return 1
Archanafdbbcba2022-02-27 05:38:55 +0530171 generate_driver_wrapper_file(template_directory, output_directory, merged_driver_json)
Archanae03960e2021-12-19 09:17:04 +0530172
173 return 0
174
175if __name__ == '__main__':
176 sys.exit(main())