From fdbbcba3eb771fb0aae8679448a09678709aa93c Mon Sep 17 00:00:00 2001 From: Archana Date: Sun, 27 Feb 2022 05:38:55 +0530 Subject: [PATCH] JSONschema and python improvements * JSON Schema manually updated to be more semantically valid. * Python script improved to be more verbose with exceptions * Templating file improved by adding an additional macro. Signed-off-by: Archana Signed-off-by: Asfandyar Orakzai --- .../driver_jsons/driver_opaque_schema.json | 90 ++++++----------- .../driver_transparent_schema.json | 92 ++++++----------- .../mbedtls_test_opaque_driver.json | 12 +-- .../mbedtls_test_transparent_driver.json | 10 +- .../driver_templates/OS-template-opaque.jinja | 15 +-- .../OS-template-transparent.jinja | 15 +-- .../psa_crypto_driver_wrappers.c.jinja | 28 ++++-- scripts/generate_driver_wrappers.py | 99 +++++++++++++------ 8 files changed, 176 insertions(+), 185 deletions(-) diff --git a/scripts/data_files/driver_jsons/driver_opaque_schema.json b/scripts/data_files/driver_jsons/driver_opaque_schema.json index 53660c8e9..4a769f0bd 100644 --- a/scripts/data_files/driver_jsons/driver_opaque_schema.json +++ b/scripts/data_files/driver_jsons/driver_opaque_schema.json @@ -2,25 +2,31 @@ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { - "prefix": { + "_comment": { "type": "string" }, + "prefix": { + "type": "string", + "pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$" + }, "type": { - "type": "string" + "type": "string", + "const": ["opaque"] }, "location": { - "type": "string" + "type": ["integer","string"], + "pattern": "^(0x|0X)?[a-fA-F0-9]+$" }, - "dependency": { + "mbedtls/h_depend_on": { "type": "string" }, "headers": { "type": "array", - "items": [ - { + "items": { "type": "string" - } - ] + }, + "minItems": 1, + "uniqueItems": true }, "capabilities": { "type": "array", @@ -31,71 +37,33 @@ "_comment": { "type": "string" }, - "depend_on": { + "mbedtls/c_depend_on": { "type": "string" }, "entry_points": { "type": "array", - "items": [ - { - "type": "string" + "items": { + "type": "string", + "enum": ["import_key", "export_key", "export_public_key", + "copy_key", "get_builtin_key"] }, - { - "type": "string" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "_comment", - "depend_on", - "entry_points" - ] - }, - { - "type": "object", - "properties": { - "_comment": { - "type": "string" - }, - "depend_on": { - "type": "string" - }, - "entry_points": { - "type": "array", - "items": [ - { - "type": "string" - }, - { - "type": "string" - } - ] + "minItems": 1, + "uniqueItems": true }, "name": { "type": "object", - "properties": { - "copy_key": { - "type": "string" - }, - "get_builtin_key": { - "type": "string" + "patternProperties": { + "^[A-Z_a-z][0-9A-Z_a-z]*$": { + "type": "string", + "pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$" } }, - "required": [ - "copy_key", - "get_builtin_key" - ] + "minItems": 1, + "uniqueItems": true } }, "required": [ - "_comment", - "depend_on", - "entry_points", - "name" + "entry_points" ] } ] @@ -105,8 +73,6 @@ "prefix", "type", "location", - "dependency", - "headers", "capabilities" ] } diff --git a/scripts/data_files/driver_jsons/driver_transparent_schema.json b/scripts/data_files/driver_jsons/driver_transparent_schema.json index dd1178d63..bf86ceb61 100644 --- a/scripts/data_files/driver_jsons/driver_transparent_schema.json +++ b/scripts/data_files/driver_jsons/driver_transparent_schema.json @@ -2,22 +2,27 @@ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { - "prefix": { + "_comment": { "type": "string" }, + "prefix": { + "type": "string", + "pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$" + }, "type": { - "type": "string" + "type": "string", + "const": ["transparent"] }, - "dependency": { + "mbedtls/h_depend_on": { "type": "string" }, "headers": { "type": "array", - "items": [ - { + "items": { "type": "string" - } - ] + }, + "minItems": 1, + "uniqueItems": true }, "capabilities": { "type": "array", @@ -28,79 +33,46 @@ "_comment": { "type": "string" }, - "depend_on": { + "mbedtls/c_depend_on": { "type": "string" }, "entry_points": { "type": "array", - "items": [ - { - "type": "string" + "items": { + "type": "string", + "enum": ["import_key", "export_key", "export_public_key", + "copy_key", "get_builtin_key"] }, - { - "type": "string" - } - ] - }, - "fallback": { - "type": "boolean" - } - }, - "required": [ - "_comment", - "depend_on", - "entry_points", - "fallback" - ] - }, - { - "type": "object", - "properties": { - "_comment": { - "type": "string" - }, - "depend_on": { - "type": "string" - }, - "entry_points": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - }, - "fallback": { - "type": "boolean" + "minItems": 1, + "uniqueItems": true }, "name": { "type": "object", - "properties": { - "export_public_key": { - "type": "string" + "patternProperties": { + "^[A-Z_a-z][0-9A-Z_a-z]*$": { + "type": "string", + "pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$" } }, - "required": [ - "export_public_key" - ] + "minItems": 1, + "uniqueItems": true + }, + "fallback": { + "type": "boolean", + "default": "false" } }, "required": [ - "_comment", - "depend_on", - "entry_points", - "fallback", - "name" + "entry_points" ] } - ] + ], + "default": [] } }, "required": [ "prefix", "type", - "dependency", - "headers", "capabilities" ] } diff --git a/scripts/data_files/driver_jsons/mbedtls_test_opaque_driver.json b/scripts/data_files/driver_jsons/mbedtls_test_opaque_driver.json index 374740455..a38287d5a 100644 --- a/scripts/data_files/driver_jsons/mbedtls_test_opaque_driver.json +++ b/scripts/data_files/driver_jsons/mbedtls_test_opaque_driver.json @@ -2,18 +2,18 @@ "prefix": "mbedtls_test", "type": "opaque", "location": "0x7fffff", - "dependency": "defined(PSA_CRYPTO_DRIVER_TEST)", + "mbedtls/h_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "headers": ["test/drivers/test_driver.h"], "capabilities": [ { - "_comment": "The mbedTLS opaque driver supports import key/export key/export_public key", - "depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", + "_comment": "The Mbed TLS opaque driver supports import key/export key/export_public key", + "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "entry_points": ["import_key", "export_key", "export_public_key"] }, { - "_comment": "The mbedTLS opaque driver supports copy key/ get builtin key", - "depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", - "entry_points": ["copy_key","get_builtin_key"], + "_comment": "The Mbed TLS opaque driver supports copy key/ get builtin key", + "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", + "entry_points": ["copy_key", "get_builtin_key"], "name": {"copy_key":"mbedtls_test_opaque_copy_key", "get_builtin_key":"mbedtls_test_opaque_get_builtin_key"} } ] diff --git a/scripts/data_files/driver_jsons/mbedtls_test_transparent_driver.json b/scripts/data_files/driver_jsons/mbedtls_test_transparent_driver.json index 52f6cd300..5c9b9feac 100644 --- a/scripts/data_files/driver_jsons/mbedtls_test_transparent_driver.json +++ b/scripts/data_files/driver_jsons/mbedtls_test_transparent_driver.json @@ -1,18 +1,18 @@ { "prefix": "mbedtls_test", "type": "transparent", - "dependency": "defined(PSA_CRYPTO_DRIVER_TEST)", + "mbedtls/h_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "headers": ["test/drivers/test_driver.h"], "capabilities": [ { - "_comment": "The mbedTLS transparent driver supports import key/export key", - "depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", + "_comment": "The Mbed TLS transparent driver supports import key/export key", + "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "entry_points": ["import_key", "export_key"], "fallback": true }, { - "_comment": "The mbedTLS transparent driver supports export_public key", - "depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", + "_comment": "The Mbed TLS transparent driver supports export_public key", + "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "entry_points": ["export_public_key"], "fallback": true, "name": {"export_public_key":"mbedtls_test_transparent_export_public_key"} diff --git a/scripts/data_files/driver_templates/OS-template-opaque.jinja b/scripts/data_files/driver_templates/OS-template-opaque.jinja index f11ac770b..115e22c86 100644 --- a/scripts/data_files/driver_templates/OS-template-opaque.jinja +++ b/scripts/data_files/driver_templates/OS-template-opaque.jinja @@ -1,13 +1,16 @@ +{# One Shot function's dispatch code for opaque drivers. +Expected inputs: +* drivers: the list of driver descriptions. +* entry_point: the name of the entry point that this function dispatches to. +* entry_point_param(driver): the parameters to pass to the entry point. +* nest_indent: number of extra spaces to indent the code to. +-#} {% for driver in drivers if driver.type == "opaque" -%} {% for capability in driver.capabilities if entry_point in capability.entry_points -%} -#if ({% if capability.depend_on is defined -%}{{ capability.depend_on }} {% else -%} {{ 1 }} {% endif %}) +#if ({% if capability['mbedtls/c_depend_on'] is defined -%}{{ capability['mbedtls/c_depend_on'] }} {% else -%} {{ 1 }} {% endif %}) {%- filter indent(width = nest_indent) %} case {{ driver.location }}: - {% if capability.name is defined and entry_point in capability.name.keys() -%} - return({{ capability.name[entry_point]}}({{entry_point_attributes(driver) | indent(20)}})); - {% else -%} - return({{driver.prefix}}_{{driver.type}}_{{entry_point}}({{entry_point_attributes(driver) | indent(20)}})); - {% endif -%} + return( {{ entry_point_name(capability, entry_point, driver) }}({{entry_point_param(driver) | indent(20)}})); {% endfilter -%} #endif {% endfor %} diff --git a/scripts/data_files/driver_templates/OS-template-transparent.jinja b/scripts/data_files/driver_templates/OS-template-transparent.jinja index 4eadd1e40..9ba115568 100644 --- a/scripts/data_files/driver_templates/OS-template-transparent.jinja +++ b/scripts/data_files/driver_templates/OS-template-transparent.jinja @@ -1,12 +1,15 @@ +{# One Shot function's dispatch code for transparent drivers. +Expected inputs: +* drivers: the list of driver descriptions. +* entry_point: the name of the entry point that this function dispatches to. +* entry_point_param(driver): the parameters to pass to the entry point. +* nest_indent: number of extra spaces to indent the code to. +-#} {% for driver in drivers if driver.type == "transparent" -%} {% for capability in driver.capabilities if entry_point in capability.entry_points -%} -#if ({% if capability.depend_on is defined -%}{{ capability.depend_on }} {% else -%} {{ 1 }} {% endif %}) +#if ({% if capability['mbedtls/c_depend_on'] is defined -%}{{ capability['mbedtls/c_depend_on'] }} {% else -%} {{ 1 }} {% endif %}) {%- filter indent(width = nest_indent) %} -{% if capability.name is defined and entry_point in capability.name.keys() -%} -status = {{ capability.name[entry_point]}}({{entry_point_attributes(driver) | indent(20)}}); -{% else -%} -status = {{driver.prefix}}_{{driver.type}}_{{entry_point}}({{entry_point_attributes(driver) | indent(20)}}); -{% endif -%} +status = {{ entry_point_name(capability, entry_point, driver) }}({{entry_point_param(driver) | indent(20)}}); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja index bea02a506..b90a9c89d 100644 --- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja +++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja @@ -1,7 +1,7 @@ /* * Functions to delegate cryptographic operations to an available * and appropriate accelerator. - * Warning: This file will be auto-generated in the future. + * Warning: This file is now auto-generated. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 @@ -39,13 +39,15 @@ #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) {% for driver in drivers -%} /* Headers for {{driver.prefix}} {{driver.type}} driver */ -{% if driver.dependency is defined -%} -#if {{ driver.dependency }} +{% if driver['mbedtls/h_depend_on'] is defined -%} +#if {{ driver['mbedtls/h_depend_on'] }} {% endif -%} {% for header in driver.headers -%} #include "{{ header }}" {% endfor %} +{% if driver['mbedtls/h_depend_on'] is defined -%} #endif +{% endif -%} {% endfor %} #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ /* END-driver headers */ @@ -60,6 +62,16 @@ {% endfor %} /* END-driver id */ +/* BEGIN-Common Macro definitions */ +{% macro entry_point_name(capability, entry_point, driver) -%} + {% if capability.name is defined and entry_point in capability.name.keys() -%} + {{ capability.name[entry_point]}} + {% else -%} + {{driver.prefix}}_{{driver.type}}_{{entry_point}} + {% endif -%} +{% endmacro %} +/* END-Common Macro definitions */ + /* Support the 'old' SE interface when asked to */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style @@ -595,7 +607,7 @@ psa_status_t psa_driver_wrapper_import_key( size_t *bits ) { {% set entry_point = "import_key" -%} -{% macro entry_point_attributes(driver) -%} +{% macro entry_point_param(driver) -%} attributes, data, data_length, @@ -677,7 +689,7 @@ psa_status_t psa_driver_wrapper_export_key( { {% set entry_point = "export_key" -%} -{% macro entry_point_attributes(driver) -%} +{% macro entry_point_param(driver) -%} attributes, key_buffer, key_buffer_size, @@ -740,7 +752,7 @@ psa_status_t psa_driver_wrapper_export_public_key( { {% set entry_point = "export_public_key" -%} -{% macro entry_point_attributes(driver) -%} +{% macro entry_point_param(driver) -%} attributes, key_buffer, key_buffer_size, @@ -812,7 +824,7 @@ psa_status_t psa_driver_wrapper_get_builtin_key( uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { {% set entry_point = "get_builtin_key" -%} -{% macro entry_point_attributes(driver) -%} +{% macro entry_point_param(driver) -%} slot_number, attributes, key_buffer, @@ -845,7 +857,7 @@ psa_status_t psa_driver_wrapper_copy_key( size_t *target_key_buffer_length ) { {% set entry_point = "copy_key" -%} -{% macro entry_point_attributes(driver) -%} +{% macro entry_point_param(driver) -%} attributes, source_key, source_key_length, diff --git a/scripts/generate_driver_wrappers.py b/scripts/generate_driver_wrappers.py index 3b6032028..3d9be88e2 100755 --- a/scripts/generate_driver_wrappers.py +++ b/scripts/generate_driver_wrappers.py @@ -23,13 +23,15 @@ import sys import os import json -from typing import Tuple +from typing import Tuple, NewType import argparse import jsonschema -from jsonschema import validate import jinja2 from mbedtls_dev import build_tree +JSONSchema = NewType('JSONSchema', object) +Driver = NewType('Driver', object) + def render(template_path: str, driver_jsoncontext: list) -> str: """ Render template from the input file and driver JSON. @@ -56,45 +58,68 @@ def generate_driver_wrapper_file(template_dir: str, \ out_file.write(result) -def validate_json(driverjson_data: list, driverschema: list) -> bool: +def validate_json(driverjson_data: Driver, driverschema_list: dict) -> bool: """ - Validate the Driver JSON against schema + Validate the Driver JSON against an appropriate schema + the schema passed could be that matching an opaque/ transparent driver. """ + + driver_type = driverjson_data["type"] + driver_prefix = driverjson_data["prefix"] try: - validate(instance=driverjson_data, schema=driverschema) + _schema = driverschema_list[driver_type] + jsonschema.validate(instance=driverjson_data, schema=_schema) + + except KeyError as err: + # This could happen if the driverjson_data.type does not exist in the passed in schema list + # schemas = {'transparent': transparent_driver_schema, 'opaque': opaque_driver_schema} + # Print onto stdout and stderr. + print("Unknown Driver type " + driver_type + + " for driver " + driver_prefix, str(err)) + print("Unknown Driver type " + driver_type + + " for driver " + driver_prefix, str(err), file=sys.stderr) + return False + except jsonschema.exceptions.ValidationError as err: - print(err) - print("The driver JSON data is InValid") + # Print onto stdout and stderr. + print("Error: Failed to validate data file: {} using schema: {}." + "\n Exception Message: \"{}\"" + " ".format(driverjson_data, _schema, str(err))) + print("Error: Failed to validate data file: {} using schema: {}." + "\n Exception Message: \"{}\"" + " ".format(driverjson_data, _schema, str(err)), file=sys.stderr) return False return True -def merge_driverjsonfiles(mbedtls_root: str, json_directory: str, \ +def read_driver_descriptions(mbedtls_root: str, json_directory: str, \ jsondriver_list: str) -> Tuple[bool, list]: """ Merge driver JSON files into a single ordered JSON after validation. """ - result = list() - driverlist = list() - with open(os.path.join(mbedtls_root, \ - 'scripts/data_files/driver_jsons/driver_transparent_schema.json'), 'r') as file: + result = [] + with open(os.path.join(mbedtls_root, + 'scripts', + 'data_files', + 'driver_jsons', + 'driver_transparent_schema.json'), 'r') as file: transparent_driver_schema = json.load(file) - with open(os.path.join(mbedtls_root, \ - 'scripts/data_files/driver_jsons/driver_opaque_schema.json'), 'r') as file: + with open(os.path.join(mbedtls_root, + 'scripts', + 'data_files', + 'driver_jsons', + 'driver_opaque_schema.json'), 'r') as file: opaque_driver_schema = json.load(file) + driver_schema_list = {'transparent':transparent_driver_schema, + 'opaque':opaque_driver_schema} + with open(os.path.join(json_directory, jsondriver_list), 'r') as driverlistfile: driverlist = json.load(driverlistfile) for file_name in driverlist: with open(os.path.join(json_directory, file_name), 'r') as infile: json_data = json.load(infile) - if json_data['type'] == 'transparent': - ret = validate_json(json_data, transparent_driver_schema) - elif json_data['type'] == 'opaque': - ret = validate_json(json_data, opaque_driver_schema) - else: - ret = False - print("Unknown Driver type") + ret = validate_json(json_data, driver_schema_list) if ret is False: return ret, [] result.append(json_data) @@ -104,35 +129,45 @@ def merge_driverjsonfiles(mbedtls_root: str, json_directory: str, \ def main() -> int: """ Main with command line arguments. + returns 1 when read_driver_descriptions returns False """ def_arg_mbedtls_root = build_tree.guess_mbedtls_root() def_arg_output_dir = os.path.join(def_arg_mbedtls_root, 'library') - def_arg_template_dir = os.path.join(def_arg_mbedtls_root, \ - 'scripts/data_files/driver_templates/') - def_arg_json_dir = os.path.join(def_arg_mbedtls_root, \ - 'scripts/data_files/driver_jsons/') + def_arg_template_dir = os.path.join(def_arg_mbedtls_root, + 'scripts', + 'data_files', + 'driver_templates') + def_arg_json_dir = os.path.join(def_arg_mbedtls_root, + 'scripts', + 'data_files', + 'driver_jsons') parser = argparse.ArgumentParser() parser.add_argument('--mbedtls-root', nargs='?', default=def_arg_mbedtls_root, help='root directory of mbedtls source code') - parser.add_argument('--template_dir', nargs='?', default=def_arg_template_dir, + parser.add_argument('--template-dir', nargs='?', default=def_arg_template_dir, help='root directory of mbedtls source code') - parser.add_argument('--json_dir', nargs='?', default=def_arg_json_dir, + parser.add_argument('--json-dir', nargs='?', default=def_arg_json_dir, help='root directory of mbedtls source code') - parser.add_argument('output_directory', nargs='?', + parser.add_argument('output-directory', nargs='?', default=def_arg_output_dir, help='output file\'s location') args = parser.parse_args() mbedtls_root = os.path.abspath(args.mbedtls_root) - output_directory = args.output_directory + output_directory = def_arg_output_dir + if args.template_dir is None: + args.template_dir = os.path.join(args.mbedtls_root, def_arg_template_dir) template_directory = args.template_dir + if args.json_dir is None: + args.json_dir = os.path.join(args.mbedtls_root, def_arg_json_dir) json_directory = args.json_dir - # load list of driver jsons from driverlist.json - ret, merged_driverjson = merge_driverjsonfiles(mbedtls_root, json_directory, 'driverlist.json') + # Read and validate list of driver jsons from driverlist.json + ret, merged_driver_json = read_driver_descriptions(mbedtls_root, json_directory, + 'driverlist.json') if ret is False: return 1 - generate_driver_wrapper_file(template_directory, output_directory, merged_driverjson) + generate_driver_wrapper_file(template_directory, output_directory, merged_driver_json) return 0