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 <archana.madhavan@silabs.com>
Signed-off-by: Asfandyar Orakzai <asfandyar.orakzai@silabs.com>
This commit is contained in:
Archana 2022-02-27 05:38:55 +05:30 committed by Asfandyar Orakzai
parent e17071a5ee
commit fdbbcba3eb
8 changed files with 176 additions and 185 deletions

View File

@ -2,25 +2,31 @@
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"type": "object", "type": "object",
"properties": { "properties": {
"prefix": { "_comment": {
"type": "string" "type": "string"
}, },
"prefix": {
"type": "string",
"pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$"
},
"type": { "type": {
"type": "string" "type": "string",
"const": ["opaque"]
}, },
"location": { "location": {
"type": "string" "type": ["integer","string"],
"pattern": "^(0x|0X)?[a-fA-F0-9]+$"
}, },
"dependency": { "mbedtls/h_depend_on": {
"type": "string" "type": "string"
}, },
"headers": { "headers": {
"type": "array", "type": "array",
"items": [ "items": {
{
"type": "string" "type": "string"
} },
] "minItems": 1,
"uniqueItems": true
}, },
"capabilities": { "capabilities": {
"type": "array", "type": "array",
@ -31,71 +37,33 @@
"_comment": { "_comment": {
"type": "string" "type": "string"
}, },
"depend_on": { "mbedtls/c_depend_on": {
"type": "string" "type": "string"
}, },
"entry_points": { "entry_points": {
"type": "array", "type": "array",
"items": [ "items": {
{ "type": "string",
"type": "string" "enum": ["import_key", "export_key", "export_public_key",
"copy_key", "get_builtin_key"]
}, },
{ "minItems": 1,
"type": "string" "uniqueItems": true
},
{
"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"
}
]
}, },
"name": { "name": {
"type": "object", "type": "object",
"properties": { "patternProperties": {
"copy_key": { "^[A-Z_a-z][0-9A-Z_a-z]*$": {
"type": "string" "type": "string",
"pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$"
}
}, },
"get_builtin_key": { "minItems": 1,
"type": "string" "uniqueItems": true
} }
}, },
"required": [ "required": [
"copy_key", "entry_points"
"get_builtin_key"
]
}
},
"required": [
"_comment",
"depend_on",
"entry_points",
"name"
] ]
} }
] ]
@ -105,8 +73,6 @@
"prefix", "prefix",
"type", "type",
"location", "location",
"dependency",
"headers",
"capabilities" "capabilities"
] ]
} }

View File

@ -2,22 +2,27 @@
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"type": "object", "type": "object",
"properties": { "properties": {
"prefix": { "_comment": {
"type": "string" "type": "string"
}, },
"prefix": {
"type": "string",
"pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$"
},
"type": { "type": {
"type": "string" "type": "string",
"const": ["transparent"]
}, },
"dependency": { "mbedtls/h_depend_on": {
"type": "string" "type": "string"
}, },
"headers": { "headers": {
"type": "array", "type": "array",
"items": [ "items": {
{
"type": "string" "type": "string"
} },
] "minItems": 1,
"uniqueItems": true
}, },
"capabilities": { "capabilities": {
"type": "array", "type": "array",
@ -28,79 +33,46 @@
"_comment": { "_comment": {
"type": "string" "type": "string"
}, },
"depend_on": { "mbedtls/c_depend_on": {
"type": "string" "type": "string"
}, },
"entry_points": { "entry_points": {
"type": "array", "type": "array",
"items": [ "items": {
{ "type": "string",
"type": "string" "enum": ["import_key", "export_key", "export_public_key",
"copy_key", "get_builtin_key"]
}, },
{ "minItems": 1,
"type": "string" "uniqueItems": true
}
]
},
"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"
}, },
"name": { "name": {
"type": "object", "type": "object",
"properties": { "patternProperties": {
"export_public_key": { "^[A-Z_a-z][0-9A-Z_a-z]*$": {
"type": "string" "type": "string",
"pattern": "^[A-Z_a-z][0-9A-Z_a-z]*$"
}
},
"minItems": 1,
"uniqueItems": true
},
"fallback": {
"type": "boolean",
"default": "false"
} }
}, },
"required": [ "required": [
"export_public_key" "entry_points"
] ]
} }
}, ],
"required": [ "default": []
"_comment",
"depend_on",
"entry_points",
"fallback",
"name"
]
}
]
} }
}, },
"required": [ "required": [
"prefix", "prefix",
"type", "type",
"dependency",
"headers",
"capabilities" "capabilities"
] ]
} }

View File

@ -2,18 +2,18 @@
"prefix": "mbedtls_test", "prefix": "mbedtls_test",
"type": "opaque", "type": "opaque",
"location": "0x7fffff", "location": "0x7fffff",
"dependency": "defined(PSA_CRYPTO_DRIVER_TEST)", "mbedtls/h_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)",
"headers": ["test/drivers/test_driver.h"], "headers": ["test/drivers/test_driver.h"],
"capabilities": [ "capabilities": [
{ {
"_comment": "The mbedTLS opaque driver supports import key/export key/export_public key", "_comment": "The Mbed TLS opaque driver supports import key/export key/export_public key",
"depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)",
"entry_points": ["import_key", "export_key", "export_public_key"] "entry_points": ["import_key", "export_key", "export_public_key"]
}, },
{ {
"_comment": "The mbedTLS opaque driver supports copy key/ get builtin key", "_comment": "The Mbed TLS opaque driver supports copy key/ get builtin key",
"depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)",
"entry_points": ["copy_key","get_builtin_key"], "entry_points": ["copy_key", "get_builtin_key"],
"name": {"copy_key":"mbedtls_test_opaque_copy_key", "get_builtin_key":"mbedtls_test_opaque_get_builtin_key"} "name": {"copy_key":"mbedtls_test_opaque_copy_key", "get_builtin_key":"mbedtls_test_opaque_get_builtin_key"}
} }
] ]

View File

@ -1,18 +1,18 @@
{ {
"prefix": "mbedtls_test", "prefix": "mbedtls_test",
"type": "transparent", "type": "transparent",
"dependency": "defined(PSA_CRYPTO_DRIVER_TEST)", "mbedtls/h_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)",
"headers": ["test/drivers/test_driver.h"], "headers": ["test/drivers/test_driver.h"],
"capabilities": [ "capabilities": [
{ {
"_comment": "The mbedTLS transparent driver supports import key/export key", "_comment": "The Mbed TLS transparent driver supports import key/export key",
"depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)",
"entry_points": ["import_key", "export_key"], "entry_points": ["import_key", "export_key"],
"fallback": true "fallback": true
}, },
{ {
"_comment": "The mbedTLS transparent driver supports export_public key", "_comment": "The Mbed TLS transparent driver supports export_public key",
"depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)", "mbedtls/c_depend_on": "defined(PSA_CRYPTO_DRIVER_TEST)",
"entry_points": ["export_public_key"], "entry_points": ["export_public_key"],
"fallback": true, "fallback": true,
"name": {"export_public_key":"mbedtls_test_transparent_export_public_key"} "name": {"export_public_key":"mbedtls_test_transparent_export_public_key"}

View File

@ -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 driver in drivers if driver.type == "opaque" -%}
{% for capability in driver.capabilities if entry_point in capability.entry_points -%} {% 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) %} {%- filter indent(width = nest_indent) %}
case {{ driver.location }}: case {{ driver.location }}:
{% if capability.name is defined and entry_point in capability.name.keys() -%} return( {{ entry_point_name(capability, entry_point, driver) }}({{entry_point_param(driver) | indent(20)}}));
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 -%}
{% endfilter -%} {% endfilter -%}
#endif #endif
{% endfor %} {% endfor %}

View File

@ -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 driver in drivers if driver.type == "transparent" -%}
{% for capability in driver.capabilities if entry_point in capability.entry_points -%} {% 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) %} {%- filter indent(width = nest_indent) %}
{% if capability.name is defined and entry_point in capability.name.keys() -%} status = {{ entry_point_name(capability, entry_point, driver) }}({{entry_point_param(driver) | indent(20)}});
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 -%}
if( status != PSA_ERROR_NOT_SUPPORTED ) if( status != PSA_ERROR_NOT_SUPPORTED )
return( status ); return( status );

View File

@ -1,7 +1,7 @@
/* /*
* Functions to delegate cryptographic operations to an available * Functions to delegate cryptographic operations to an available
* and appropriate accelerator. * 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 /* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
@ -39,13 +39,15 @@
#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
{% for driver in drivers -%} {% for driver in drivers -%}
/* Headers for {{driver.prefix}} {{driver.type}} driver */ /* Headers for {{driver.prefix}} {{driver.type}} driver */
{% if driver.dependency is defined -%} {% if driver['mbedtls/h_depend_on'] is defined -%}
#if {{ driver.dependency }} #if {{ driver['mbedtls/h_depend_on'] }}
{% endif -%} {% endif -%}
{% for header in driver.headers -%} {% for header in driver.headers -%}
#include "{{ header }}" #include "{{ header }}"
{% endfor %} {% endfor %}
{% if driver['mbedtls/h_depend_on'] is defined -%}
#endif #endif
{% endif -%}
{% endfor %} {% endfor %}
#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
/* END-driver headers */ /* END-driver headers */
@ -60,6 +62,16 @@
{% endfor %} {% endfor %}
/* END-driver id */ /* 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 */ /* Support the 'old' SE interface when asked to */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C) #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style /* 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 ) size_t *bits )
{ {
{% set entry_point = "import_key" -%} {% set entry_point = "import_key" -%}
{% macro entry_point_attributes(driver) -%} {% macro entry_point_param(driver) -%}
attributes, attributes,
data, data,
data_length, data_length,
@ -677,7 +689,7 @@ psa_status_t psa_driver_wrapper_export_key(
{ {
{% set entry_point = "export_key" -%} {% set entry_point = "export_key" -%}
{% macro entry_point_attributes(driver) -%} {% macro entry_point_param(driver) -%}
attributes, attributes,
key_buffer, key_buffer,
key_buffer_size, key_buffer_size,
@ -740,7 +752,7 @@ psa_status_t psa_driver_wrapper_export_public_key(
{ {
{% set entry_point = "export_public_key" -%} {% set entry_point = "export_public_key" -%}
{% macro entry_point_attributes(driver) -%} {% macro entry_point_param(driver) -%}
attributes, attributes,
key_buffer, key_buffer,
key_buffer_size, 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 ) uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{ {
{% set entry_point = "get_builtin_key" -%} {% set entry_point = "get_builtin_key" -%}
{% macro entry_point_attributes(driver) -%} {% macro entry_point_param(driver) -%}
slot_number, slot_number,
attributes, attributes,
key_buffer, key_buffer,
@ -845,7 +857,7 @@ psa_status_t psa_driver_wrapper_copy_key(
size_t *target_key_buffer_length ) size_t *target_key_buffer_length )
{ {
{% set entry_point = "copy_key" -%} {% set entry_point = "copy_key" -%}
{% macro entry_point_attributes(driver) -%} {% macro entry_point_param(driver) -%}
attributes, attributes,
source_key, source_key,
source_key_length, source_key_length,

View File

@ -23,13 +23,15 @@
import sys import sys
import os import os
import json import json
from typing import Tuple from typing import Tuple, NewType
import argparse import argparse
import jsonschema import jsonschema
from jsonschema import validate
import jinja2 import jinja2
from mbedtls_dev import build_tree from mbedtls_dev import build_tree
JSONSchema = NewType('JSONSchema', object)
Driver = NewType('Driver', object)
def render(template_path: str, driver_jsoncontext: list) -> str: def render(template_path: str, driver_jsoncontext: list) -> str:
""" """
Render template from the input file and driver JSON. 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) 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: 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: except jsonschema.exceptions.ValidationError as err:
print(err) # Print onto stdout and stderr.
print("The driver JSON data is InValid") 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 False
return True 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]: jsondriver_list: str) -> Tuple[bool, list]:
""" """
Merge driver JSON files into a single ordered JSON after validation. Merge driver JSON files into a single ordered JSON after validation.
""" """
result = list() result = []
driverlist = list() with open(os.path.join(mbedtls_root,
with open(os.path.join(mbedtls_root, \ 'scripts',
'scripts/data_files/driver_jsons/driver_transparent_schema.json'), 'r') as file: 'data_files',
'driver_jsons',
'driver_transparent_schema.json'), 'r') as file:
transparent_driver_schema = json.load(file) transparent_driver_schema = json.load(file)
with open(os.path.join(mbedtls_root, \ with open(os.path.join(mbedtls_root,
'scripts/data_files/driver_jsons/driver_opaque_schema.json'), 'r') as file: 'scripts',
'data_files',
'driver_jsons',
'driver_opaque_schema.json'), 'r') as file:
opaque_driver_schema = json.load(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: with open(os.path.join(json_directory, jsondriver_list), 'r') as driverlistfile:
driverlist = json.load(driverlistfile) driverlist = json.load(driverlistfile)
for file_name in driverlist: for file_name in driverlist:
with open(os.path.join(json_directory, file_name), 'r') as infile: with open(os.path.join(json_directory, file_name), 'r') as infile:
json_data = json.load(infile) json_data = json.load(infile)
if json_data['type'] == 'transparent': ret = validate_json(json_data, driver_schema_list)
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")
if ret is False: if ret is False:
return ret, [] return ret, []
result.append(json_data) result.append(json_data)
@ -104,35 +129,45 @@ def merge_driverjsonfiles(mbedtls_root: str, json_directory: str, \
def main() -> int: def main() -> int:
""" """
Main with command line arguments. Main with command line arguments.
returns 1 when read_driver_descriptions returns False
""" """
def_arg_mbedtls_root = build_tree.guess_mbedtls_root() def_arg_mbedtls_root = build_tree.guess_mbedtls_root()
def_arg_output_dir = os.path.join(def_arg_mbedtls_root, 'library') def_arg_output_dir = os.path.join(def_arg_mbedtls_root, 'library')
def_arg_template_dir = os.path.join(def_arg_mbedtls_root, \ def_arg_template_dir = os.path.join(def_arg_mbedtls_root,
'scripts/data_files/driver_templates/') 'scripts',
def_arg_json_dir = os.path.join(def_arg_mbedtls_root, \ 'data_files',
'scripts/data_files/driver_jsons/') 'driver_templates')
def_arg_json_dir = os.path.join(def_arg_mbedtls_root,
'scripts',
'data_files',
'driver_jsons')
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--mbedtls-root', nargs='?', default=def_arg_mbedtls_root, parser.add_argument('--mbedtls-root', nargs='?', default=def_arg_mbedtls_root,
help='root directory of mbedtls source code') 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') 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') 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') default=def_arg_output_dir, help='output file\'s location')
args = parser.parse_args() args = parser.parse_args()
mbedtls_root = os.path.abspath(args.mbedtls_root) 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 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 json_directory = args.json_dir
# load list of driver jsons from driverlist.json # Read and validate list of driver jsons from driverlist.json
ret, merged_driverjson = merge_driverjsonfiles(mbedtls_root, json_directory, 'driverlist.json') ret, merged_driver_json = read_driver_descriptions(mbedtls_root, json_directory,
'driverlist.json')
if ret is False: if ret is False:
return 1 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 return 0