1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-02 20:42:25 +03:00

Added framework as a flattened directory

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
This commit is contained in:
Minos Galanakis
2025-03-20 09:28:45 +00:00
parent b41194ce7f
commit 2c824b4fe5
924 changed files with 48159 additions and 0 deletions

View File

@ -0,0 +1,29 @@
""" PSA Buffer utility data-class.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
from typing import List
from .. import typing_util
class BufferParameter:
"""Description of an input or output buffer parameter sequence to a PSA function."""
#pylint: disable=too-few-public-methods
def __init__(self, i: int, is_output: bool,
buffer_name: str, size_name: str) -> None:
"""Initialize the parameter information.
i is the index of the function argument that is the pointer to the buffer.
The size is argument i+1. For a variable-size output, the actual length
goes in argument i+2.
buffer_name and size_names are the names of arguments i and i+1.
This class does not yet help with the output length.
"""
self.index = i
self.buffer_name = buffer_name
self.size_name = size_name
self.is_output = is_output

View File

@ -0,0 +1,39 @@
"""Generate wrapper functions for PSA function calls.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import argparse
import itertools
import os
from typing import Iterator, List, Collection, Optional, Tuple
from .. import build_tree
from .. import c_parsing_helper
from .. import c_wrapper_generator
from .. import typing_util
from .psa_buffer import BufferParameter
from .psa_wrapper import PSAWrapper, PSALoggingWrapper, PSAWrapperConfiguration
class PSATestWrapper(PSAWrapper):
"""Generate a C source file containing wrapper functions for PSA Crypto API calls."""
_WRAPPER_NAME_PREFIX = 'mbedtls_test_wrap_'
_WRAPPER_NAME_SUFFIX = ''
_PSA_WRAPPER_INCLUDES = ['<psa/crypto.h>',
'<test/memory.h>',
'<test/psa_crypto_helpers.h>',
'<test/psa_test_wrappers.h>']
class PSALoggingTestWrapper(PSATestWrapper, PSALoggingWrapper):
"""Generate a C source file containing wrapper functions that log PSA Crypto API calls."""
def __init__(self, out_h_f: str,
out_c_f: str,
stream: str,
in_headers: Optional[List[str]] = None) -> None:
super().__init__(out_h_f, out_c_f, stream, in_headers)

View File

@ -0,0 +1,286 @@
"""Generate wrapper functions for PSA function calls.
"""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
import argparse
import itertools
import os
from typing import Any, Iterator, List, Dict, Collection, Optional, Tuple
from .. import build_tree
from .. import c_parsing_helper
from .. import c_wrapper_generator
from .. import typing_util
from .psa_buffer import BufferParameter
class PSAWrapperConfiguration:
"""Configuration data class for PSA Wrapper."""
def __init__(self) -> None:
self.cpp_guards = ["MBEDTLS_PSA_CRYPTO_C", "MBEDTLS_TEST_HOOKS", "!RECORD_PSA_STATUS_COVERAGE_LOG"]
self.skipped_functions = frozenset([
'mbedtls_psa_external_get_random', # not a library function
'psa_get_key_domain_parameters', # client-side function
'psa_get_key_slot_number', # client-side function
'psa_key_derivation_verify_bytes', # not implemented yet
'psa_key_derivation_verify_key', # not implemented yet
'psa_set_key_domain_parameters', # client-side function
])
self.skipped_argument_types = frozenset([
# PAKE stuff: not implemented yet
'psa_crypto_driver_pake_inputs_t *',
'psa_pake_cipher_suite_t *',
])
self.function_guards = {
'mbedtls_psa_register_se_key': 'defined(MBEDTLS_PSA_CRYPTO_SE_C)',
'mbedtls_psa_inject_entropy': 'defined(MBEDTLS_PSA_INJECT_ENTROPY)',
'mbedtls_psa_external_get_random': 'defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)',
'mbedtls_psa_platform_get_builtin_key': 'defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)',
'psa_crypto_driver_pake_get_cipher_suite' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_crypto_driver_pake_get_password' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_crypto_driver_pake_get_password_len' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_crypto_driver_pake_get_peer' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_crypto_driver_pake_get_peer_len' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_crypto_driver_pake_get_user' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_crypto_driver_pake_get_user_len' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_abort' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_get_implicit_key' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_input' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_output' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_set_password_key' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_set_peer' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_set_role' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_set_user' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
'psa_pake_setup' : 'defined(PSA_WANT_ALG_SOME_PAKE)',
}
class PSAWrapper(c_wrapper_generator.Base):
"""Generate a C source file containing wrapper functions for PSA Crypto API calls."""
_WRAPPER_NAME_PREFIX = 'mbedtls_test_wrap_'
_WRAPPER_NAME_SUFFIX = ''
_PSA_WRAPPER_INCLUDES = ['<psa/crypto.h>']
_DEFAULT_IN_HEADERS = ['crypto.h', 'crypto_extra.h']
def __init__(self,
out_h_f: str,
out_c_f: str,
in_headers: Optional[List[str]] = None,
config: PSAWrapperConfiguration = PSAWrapperConfiguration()) -> None:
super().__init__()
self.out_c_f = out_c_f
self.out_h_f = out_h_f
self.mbedtls_root = build_tree.guess_mbedtls_root()
self.read_config(config)
self.read_headers(in_headers)
def read_config(self, cfg: PSAWrapperConfiguration)-> None:
"""Configure instance's parameters from a user provided config."""
self._cpp_guards = PSAWrapper.parse_def_guards(cfg.cpp_guards)
self._skip_functions = cfg.skipped_functions
self._function_guards.update(cfg.function_guards)
self._not_implemented = cfg.skipped_argument_types
def read_headers(self, headers: Optional[List[str]]) -> None:
"""Reads functions to be wrapped from source header files into self.functions."""
self.in_headers = self._DEFAULT_IN_HEADERS if headers is None else headers
for header_name in self.in_headers:
header_path = self.rel_path(header_name)
c_parsing_helper.read_function_declarations(self.functions, header_path)
def rel_path(self, filename: str, path_list: List[str] = ['include', 'psa']) -> str:
"""Return the estimated path in relationship to the mbedtls_root.
The method allows overriding the targetted sub-directory.
Currently the default is set to mbedtls_root/include/psa."""
# Temporary, while Mbed TLS does not just rely on the TF-PSA-Crypto
# build system to build its crypto library. When it does, the first
# case can just be removed.
if not build_tree.is_mbedtls_3_6():
path_list = ['tf-psa-crypto' ] + path_list
return os.path.join(self.mbedtls_root, *path_list, filename)
return os.path.join(self.mbedtls_root, *path_list, filename)
# Utility Methods
@staticmethod
def parse_def_guards(def_list: Collection[str])-> str:
""" Create define guards.
Convert an input list of into a C preprocessor
expression of defined() && !defined() syntax string."""
output = ""
dl = [("defined({})".format(n) if n[0] != "!" else
"!defined({})".format(n[1:]))
for n in def_list]
# Split the list in chunks of 2 and add new lines
for i in range(0, len(dl), 2):
output += "{} && {} && \\".format(dl[i], dl[i+1]) + "\n "\
if i+2 <= len(dl) else dl[i]
return output
@staticmethod
def _detect_buffer_parameters(arguments: List[c_parsing_helper.ArgumentInfo],
argument_names: List[str]) -> Iterator[BufferParameter]:
"""Detect function arguments that are buffers (pointer, size [,length])."""
types = ['' if arg.suffix else arg.type for arg in arguments]
# pairs = list of (type_of_arg_N, type_of_arg_N+1)
# where each type_of_arg_X is the empty string if the type is an array
# or there is no argument X.
pairs = enumerate(itertools.zip_longest(types, types[1:], fillvalue=''))
for i, t01 in pairs:
if (t01[0] == 'const uint8_t *' or t01[0] == 'uint8_t *') and \
t01[1] == 'size_t':
yield BufferParameter(i, not t01[0].startswith('const '),
argument_names[i], argument_names[i+1])
@staticmethod
def _parameter_should_be_copied(function_name: str,
_buffer_name: Optional[str]) -> bool:
"""Whether the specified buffer argument to a PSA function should be copied.
"""
# False-positives that do not need buffer copying
if function_name in ('mbedtls_psa_inject_entropy',
'psa_crypto_driver_pake_get_password',
'psa_crypto_driver_pake_get_user',
'psa_crypto_driver_pake_get_peer'):
return False
return True
def _poison_wrap(self, param : BufferParameter, poison: bool, ident_lv = 1) -> str:
"""Returns a call to MBEDTLS_TEST_MEMORY_[UN]POISON.
The output is prefixed with MBEDTLS_TEST_MEMORY_ followed by POISON/UNPOISON
and the input parameter arguments (name, length)
"""
return "{}MBEDTLS_TEST_MEMORY_{}({}, {});\n".format((ident_lv * 4) * ' ',
'POISON' if poison else 'UNPOISON',
param.buffer_name, param.size_name)
def _poison_multi_write(self,
out: typing_util.Writable,
buffer_parameters: List['BufferParameter'],
poison: bool) -> None:
"""Write poisoning or unpoisoning code for the buffer parameters.
Write poisoning code if poison is true, unpoisoning code otherwise.
"""
if not buffer_parameters:
return
out.write('#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n')
for param in buffer_parameters:
out.write(self._poison_wrap(param, poison))
out.write('#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */\n')
# Override parent's methods
def _write_function_call(self, out: typing_util.Writable,
function: c_wrapper_generator.FunctionInfo,
argument_names: List[str]) -> None:
buffer_parameters = list(
param
for param in self._detect_buffer_parameters(function.arguments,
argument_names)
if self._parameter_should_be_copied(function.name,
function.arguments[param.index].name))
self._poison_multi_write(out, buffer_parameters, True)
super()._write_function_call(out, function, argument_names)
self._poison_multi_write(out, buffer_parameters, False)
def _skip_function(self, function: c_wrapper_generator.FunctionInfo) -> bool:
if function.return_type != 'psa_status_t':
return True
if function.name in self._skip_functions:
return True
return False
def _return_variable_name(self,
function: c_wrapper_generator.FunctionInfo) -> str:
"""The name of the variable that will contain the return value."""
if function.return_type == 'psa_status_t':
return 'status'
return super()._return_variable_name(function)
def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
super()._write_prologue(out, header)
prologue = []
if self._cpp_guards:
prologue.append("#if {}".format(self._cpp_guards))
prologue.append('')
for include in self._PSA_WRAPPER_INCLUDES:
prologue.append("#include {}".format(include))
# Make certain there is an empty line at the end of this section.
for i in [-1, -2]:
if prologue[i] != '':
prologue.append('')
out.write("\n".join(prologue))
def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None:
if self._cpp_guards:
out.write("#endif /* {} */\n\n".format(self._cpp_guards))
super()._write_epilogue(out, header)
class PSALoggingWrapper(PSAWrapper, c_wrapper_generator.Logging):
"""Generate a C source file containing wrapper functions that log PSA Crypto API calls."""
def __init__(self,
stream: str,
out_h_f: str,
out_c_f: str,
in_headers: Optional[List[str]] = None,
config: PSAWrapperConfiguration = PSAWrapperConfiguration()) -> None:
super().__init__(out_h_f, out_c_f, in_headers, config)
self.set_stream(stream)
_PRINTF_TYPE_CAST = c_wrapper_generator.Logging._PRINTF_TYPE_CAST.copy()
_PRINTF_TYPE_CAST.update({
'mbedtls_svc_key_id_t': 'unsigned',
'psa_algorithm_t': 'unsigned',
'psa_drv_slot_number_t': 'unsigned long long',
'psa_key_derivation_step_t': 'int',
'psa_key_id_t': 'unsigned',
'psa_key_slot_number_t': 'unsigned long long',
'psa_key_lifetime_t': 'unsigned',
'psa_key_type_t': 'unsigned',
'psa_key_usage_flags_t': 'unsigned',
'psa_pake_role_t': 'int',
'psa_pake_step_t': 'int',
'psa_status_t': 'int',
})
def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]:
if typ.startswith('const '):
typ = typ[6:]
if typ == 'uint8_t *':
# Skip buffers
return '', []
if typ.endswith('operation_t *'):
return '', []
if typ in self._not_implemented:
return '', []
if typ == 'psa_key_attributes_t *':
return (var + '={id=%u, lifetime=0x%08x, type=0x%08x, bits=%u, alg=%08x, usage=%08x}',
['(unsigned) psa_get_key_{}({})'.format(field, var)
for field in ['id', 'lifetime', 'type', 'bits', 'algorithm', 'usage_flags']])
return super()._printf_parameters(typ, var)