blob: 3d9be88e2f4dea8c1b39566039bc4334788b2128 [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)
33Driver = NewType('Driver', object)
34
Archanae829cd62021-12-24 12:50:36 +053035def render(template_path: str, driver_jsoncontext: list) -> str:
Archanae03960e2021-12-19 09:17:04 +053036 """
Archanae829cd62021-12-24 12:50:36 +053037 Render template from the input file and driver JSON.
Archanae03960e2021-12-19 09:17:04 +053038 """
Archana6f21e452021-11-23 14:46:51 +053039 environment = jinja2.Environment(
40 loader=jinja2.FileSystemLoader(os.path.dirname(template_path)),
41 keep_trailing_newline=True)
42 template = environment.get_template(os.path.basename(template_path))
Archanae03960e2021-12-19 09:17:04 +053043
Archana31438052022-01-09 15:01:20 +053044 return template.render(drivers=driver_jsoncontext)
Archana1f1a34a2021-11-17 08:44:07 +053045
Archanae829cd62021-12-24 12:50:36 +053046
Archana31438052022-01-09 15:01:20 +053047def generate_driver_wrapper_file(template_dir: str, \
48 output_dir: str, driver_jsoncontext: list) -> None:
Archanae03960e2021-12-19 09:17:04 +053049 """
50 Generate the file psa_crypto_driver_wrapper.c.
51 """
52 driver_wrapper_template_filename = \
Archanae829cd62021-12-24 12:50:36 +053053 os.path.join(template_dir, "psa_crypto_driver_wrappers.c.jinja")
Archana1f1a34a2021-11-17 08:44:07 +053054
Archanae829cd62021-12-24 12:50:36 +053055 result = render(driver_wrapper_template_filename, driver_jsoncontext)
Archana1f1a34a2021-11-17 08:44:07 +053056
Archanae03960e2021-12-19 09:17:04 +053057 with open(os.path.join(output_dir, "psa_crypto_driver_wrappers.c"), 'w') as out_file:
58 out_file.write(result)
Archana6f21e452021-11-23 14:46:51 +053059
Archanae829cd62021-12-24 12:50:36 +053060
Archanafdbbcba2022-02-27 05:38:55 +053061def validate_json(driverjson_data: Driver, driverschema_list: dict) -> bool:
Archanae829cd62021-12-24 12:50:36 +053062 """
Archanafdbbcba2022-02-27 05:38:55 +053063 Validate the Driver JSON against an appropriate schema
64 the schema passed could be that matching an opaque/ transparent driver.
Archana04cfe342022-01-09 13:28:28 +053065 """
Archanafdbbcba2022-02-27 05:38:55 +053066
67 driver_type = driverjson_data["type"]
68 driver_prefix = driverjson_data["prefix"]
Archana04cfe342022-01-09 13:28:28 +053069 try:
Archanafdbbcba2022-02-27 05:38:55 +053070 _schema = driverschema_list[driver_type]
71 jsonschema.validate(instance=driverjson_data, schema=_schema)
72
73 except KeyError as err:
74 # This could happen if the driverjson_data.type does not exist in the passed in schema list
75 # schemas = {'transparent': transparent_driver_schema, 'opaque': opaque_driver_schema}
76 # Print onto stdout and stderr.
77 print("Unknown Driver type " + driver_type +
78 " for driver " + driver_prefix, str(err))
79 print("Unknown Driver type " + driver_type +
80 " for driver " + driver_prefix, str(err), file=sys.stderr)
81 return False
82
Archana04cfe342022-01-09 13:28:28 +053083 except jsonschema.exceptions.ValidationError as err:
Archanafdbbcba2022-02-27 05:38:55 +053084 # Print onto stdout and stderr.
85 print("Error: Failed to validate data file: {} using schema: {}."
86 "\n Exception Message: \"{}\""
87 " ".format(driverjson_data, _schema, str(err)))
88 print("Error: Failed to validate data file: {} using schema: {}."
89 "\n Exception Message: \"{}\""
90 " ".format(driverjson_data, _schema, str(err)), file=sys.stderr)
Archana04cfe342022-01-09 13:28:28 +053091 return False
92
Archana04cfe342022-01-09 13:28:28 +053093 return True
94
Archanafdbbcba2022-02-27 05:38:55 +053095def read_driver_descriptions(mbedtls_root: str, json_directory: str, \
Archana31438052022-01-09 15:01:20 +053096 jsondriver_list: str) -> Tuple[bool, list]:
Archana04cfe342022-01-09 13:28:28 +053097 """
98 Merge driver JSON files into a single ordered JSON after validation.
Archanae829cd62021-12-24 12:50:36 +053099 """
Archanafdbbcba2022-02-27 05:38:55 +0530100 result = []
101 with open(os.path.join(mbedtls_root,
102 'scripts',
103 'data_files',
104 'driver_jsons',
105 'driver_transparent_schema.json'), 'r') as file:
Archana04cfe342022-01-09 13:28:28 +0530106 transparent_driver_schema = json.load(file)
Archanafdbbcba2022-02-27 05:38:55 +0530107 with open(os.path.join(mbedtls_root,
108 'scripts',
109 'data_files',
110 'driver_jsons',
111 'driver_opaque_schema.json'), 'r') as file:
Archana04cfe342022-01-09 13:28:28 +0530112 opaque_driver_schema = json.load(file)
113
Archanafdbbcba2022-02-27 05:38:55 +0530114 driver_schema_list = {'transparent':transparent_driver_schema,
115 'opaque':opaque_driver_schema}
116
Archana31438052022-01-09 15:01:20 +0530117 with open(os.path.join(json_directory, jsondriver_list), 'r') as driverlistfile:
Archanae829cd62021-12-24 12:50:36 +0530118 driverlist = json.load(driverlistfile)
119 for file_name in driverlist:
120 with open(os.path.join(json_directory, file_name), 'r') as infile:
Archana04cfe342022-01-09 13:28:28 +0530121 json_data = json.load(infile)
Archanafdbbcba2022-02-27 05:38:55 +0530122 ret = validate_json(json_data, driver_schema_list)
Archana31438052022-01-09 15:01:20 +0530123 if ret is False:
Archana04cfe342022-01-09 13:28:28 +0530124 return ret, []
125 result.append(json_data)
126 return True, result
Archanae829cd62021-12-24 12:50:36 +0530127
128
Archanae03960e2021-12-19 09:17:04 +0530129def main() -> int:
130 """
131 Main with command line arguments.
Archanafdbbcba2022-02-27 05:38:55 +0530132 returns 1 when read_driver_descriptions returns False
Archanae03960e2021-12-19 09:17:04 +0530133 """
Archana4a9e0262021-12-19 13:34:30 +0530134 def_arg_mbedtls_root = build_tree.guess_mbedtls_root()
135 def_arg_output_dir = os.path.join(def_arg_mbedtls_root, 'library')
Archanafdbbcba2022-02-27 05:38:55 +0530136 def_arg_template_dir = os.path.join(def_arg_mbedtls_root,
137 'scripts',
138 'data_files',
139 'driver_templates')
140 def_arg_json_dir = os.path.join(def_arg_mbedtls_root,
141 'scripts',
142 'data_files',
143 'driver_jsons')
Archana4a9e0262021-12-19 13:34:30 +0530144
Archanae03960e2021-12-19 09:17:04 +0530145 parser = argparse.ArgumentParser()
Archana4a9e0262021-12-19 13:34:30 +0530146 parser.add_argument('--mbedtls-root', nargs='?', default=def_arg_mbedtls_root,
Archanae03960e2021-12-19 09:17:04 +0530147 help='root directory of mbedtls source code')
Archanafdbbcba2022-02-27 05:38:55 +0530148 parser.add_argument('--template-dir', nargs='?', default=def_arg_template_dir,
Archanae829cd62021-12-24 12:50:36 +0530149 help='root directory of mbedtls source code')
Archanafdbbcba2022-02-27 05:38:55 +0530150 parser.add_argument('--json-dir', nargs='?', default=def_arg_json_dir,
Archanae829cd62021-12-24 12:50:36 +0530151 help='root directory of mbedtls source code')
Archanafdbbcba2022-02-27 05:38:55 +0530152 parser.add_argument('output-directory', nargs='?',
Archana4a9e0262021-12-19 13:34:30 +0530153 default=def_arg_output_dir, help='output file\'s location')
Archanae03960e2021-12-19 09:17:04 +0530154 args = parser.parse_args()
Archana4a9e0262021-12-19 13:34:30 +0530155
Archana31438052022-01-09 15:01:20 +0530156 mbedtls_root = os.path.abspath(args.mbedtls_root)
Archanafdbbcba2022-02-27 05:38:55 +0530157 output_directory = def_arg_output_dir
158 if args.template_dir is None:
159 args.template_dir = os.path.join(args.mbedtls_root, def_arg_template_dir)
Archanae829cd62021-12-24 12:50:36 +0530160 template_directory = args.template_dir
Archanafdbbcba2022-02-27 05:38:55 +0530161 if args.json_dir is None:
162 args.json_dir = os.path.join(args.mbedtls_root, def_arg_json_dir)
Archana31438052022-01-09 15:01:20 +0530163 json_directory = args.json_dir
Archanae03960e2021-12-19 09:17:04 +0530164
Archanafdbbcba2022-02-27 05:38:55 +0530165 # Read and validate list of driver jsons from driverlist.json
166 ret, merged_driver_json = read_driver_descriptions(mbedtls_root, json_directory,
167 'driverlist.json')
Archana31438052022-01-09 15:01:20 +0530168 if ret is False:
Archanae829cd62021-12-24 12:50:36 +0530169 return 1
Archanafdbbcba2022-02-27 05:38:55 +0530170 generate_driver_wrapper_file(template_directory, output_directory, merged_driver_json)
Archanae03960e2021-12-19 09:17:04 +0530171
172 return 0
173
174if __name__ == '__main__':
175 sys.exit(main())