mirror of
https://github.com/Mbed-TLS/mbedtls-framework.git
synced 2026-08-13 22:57:48 +00:00
Merge pull request #311 from Mbed-TLS/framework_mergeback
MbedTLS 4.2.0 & TF-PSA-Crypto 1.2.0 Framework mergeback
This commit is contained in:
+67
-9
@@ -469,6 +469,22 @@ server5-selfsigned.crt: server5.key
|
||||
-out $@
|
||||
all_final += server5-selfsigned.crt
|
||||
|
||||
server5-selfsigned.crt.der: server5-selfsigned.crt
|
||||
$(OPENSSL) x509 -inform PEM -in $< -outform DER -out $@
|
||||
all_final += server5-selfsigned.crt.der
|
||||
|
||||
server5-ca.der: server5.key
|
||||
openssl req -x509 -key server5.key \
|
||||
-sha256 -days 3650 -nodes \
|
||||
-addext basicConstraints=critical,CA:TRUE \
|
||||
-addext keyUsage=critical,digitalSignature \
|
||||
-addext subjectKeyIdentifier=hash \
|
||||
-addext authorityKeyIdentifier=none \
|
||||
-set_serial 0x53a2cb4b124ead837da894b2 \
|
||||
-subj "/CN=selfsigned/OU=testing/O=PolarSSL/C=NL" \
|
||||
-outform DER -out $@
|
||||
all_final += server5-ca.der
|
||||
|
||||
# Create a certificate which is almost identical to "server3.crt", i.e.
|
||||
# it contains a public EC key and it is signed with RSA. The main difference
|
||||
# compared to "server3.crt" is that in this case we use a secp256r1 key ("server5.key")
|
||||
@@ -2294,6 +2310,40 @@ parse_input/server4.crt server4.crt: server4.key
|
||||
md=SHA256 version=3 output_file=$@
|
||||
all_final += server4.crt
|
||||
|
||||
# Negative tests
|
||||
|
||||
# Replace a well-formed basicConstraints extension containing CA:TRUE with
|
||||
# a malformed extension that is empty with trailing junk. The trailing
|
||||
# junk is a boolean with the value true, thus it would be interpreted as
|
||||
# CA:TRUE if it was properly inside the basicConstraints extension.
|
||||
parse_input/server5.basic-constraints-sequence-overflow.badsign.crt: server5-ca.der
|
||||
perl -0777 -pe '$$n = s/\x04\x05\x30\x03\x01\x01\xff/\x04\x05\x30\x00\x01\x01\xff/g; die "More substitutions than expected" if $$n > 1; die "Substitution not found" if $$n < 1' <$< >$@.tmp
|
||||
mv $@.tmp $@
|
||||
all_final += parse_input/server5.basic-constraints-sequence-overflow.badsign.crt
|
||||
|
||||
parse_input/server5.basic-constraints-sequence-overflow.selfsigned.crt: parse_input/server5.basic-constraints-sequence-overflow.badsign.crt server5.key
|
||||
$(OPENSSL) x509 -subj '/CN=Eve/' \
|
||||
-key server5.key \
|
||||
-days 3653 \
|
||||
-inform DER -in $< -outform DER -out $@
|
||||
all_final += parse_input/server5.basic-constraints-sequence-overflow.selfsigned.crt
|
||||
|
||||
# Replace a well-formed basicConstraints extension containing CA:TRUE with
|
||||
# a malformed extension that is empty with trailing junk. The trailing
|
||||
# junk is a boolean with the value true, thus it would be interpreted as
|
||||
# CA:TRUE if it was properly inside the basicConstraints extension.
|
||||
parse_input/server5.basic-constraints-integer-first.badsign.crt: server5-ca.der
|
||||
perl -0777 -pe '$$n = s/\x04\x05\x30\x03\x01\x01\xff/\x04\x05\x30\x03\x02\x01\x01/g; die "More substitutions than expected" if $$n > 1; die "Substitution not found" if $$n < 1' <$< >$@.tmp
|
||||
mv $@.tmp $@
|
||||
all_final += parse_input/server5.basic-constraints-integer-first.badsign.crt
|
||||
|
||||
parse_input/server5.basic-constraints-integer-first.selfsigned.crt: parse_input/server5.basic-constraints-integer-first.badsign.crt server5.key
|
||||
$(OPENSSL) x509 -subj '/CN=Eve/' \
|
||||
-key server5.key \
|
||||
-days 3653 \
|
||||
-inform DER -in $< -outform DER -out $@
|
||||
all_final += parse_input/server5.basic-constraints-integer-first.selfsigned.crt
|
||||
|
||||
# MD5 test certificate
|
||||
|
||||
cert_md_test_key = $(cli_crt_key_file_rsa)
|
||||
@@ -2388,7 +2438,7 @@ all_final += pkcs7-rsa-expired.crt
|
||||
|
||||
# File with an otherwise valid signature signed with an expired cert
|
||||
pkcs7_data_rsa_expired.der: pkcs7-rsa-expired.key pkcs7-rsa-expired.crt pkcs7_data.bin
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -inkey pkcs7-rsa-expired.key -signer pkcs7-rsa-expired.crt -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -inkey pkcs7-rsa-expired.key -signer pkcs7-rsa-expired.crt -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_rsa_expired.der
|
||||
|
||||
# Convert signing certs to DER for testing PEM-free builds
|
||||
@@ -2411,42 +2461,50 @@ all_final += pkcs7_zerolendata_detached.der
|
||||
|
||||
# pkcs7 signature file with CERT
|
||||
pkcs7_data_cert_signed_sha256.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_cert_signed_sha256.der
|
||||
|
||||
# pkcs7 signature file with CERT and sha1
|
||||
pkcs7_data_cert_signed_sha1.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha1 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha1 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_cert_signed_sha1.der
|
||||
|
||||
pkcs7_data_cert_signed_md5.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md md5 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_cert_signed_md5.der
|
||||
|
||||
pkcs7_data_cert_signed_ripemd160.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md ripemd160 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_cert_signed_ripemd160.der
|
||||
|
||||
# pkcs7 signature file with CERT and sha512
|
||||
pkcs7_data_cert_signed_sha512.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha512 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha512 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_cert_signed_sha512.der
|
||||
|
||||
# pkcs7 signature file without CERT
|
||||
pkcs7_data_without_cert_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -nocerts -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -signer pkcs7-rsa-sha256-1.pem -nocerts -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_without_cert_signed.der
|
||||
|
||||
# pkcs7 signature file with signature
|
||||
pkcs7_data_with_signature.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -nocerts -noattr -nodetach -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -signer pkcs7-rsa-sha256-1.pem -nocerts -noattr -nodetach -outform DER -out $@
|
||||
all_final += pkcs7_data_with_signature.der
|
||||
|
||||
# pkcs7 signature file with two signers
|
||||
pkcs7_data_multiple_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -nocerts -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -nocerts -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_multiple_signed.der
|
||||
|
||||
# pkcs7 signature file with three signers
|
||||
pkcs7_data_3_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2) $(pkcs7_test_cert_3)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -signer pkcs7-rsa-sha256-3.pem -nocerts -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -signer pkcs7-rsa-sha256-3.pem -nocerts -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_3_signed.der
|
||||
|
||||
# pkcs7 signature file with multiple certificates
|
||||
pkcs7_data_multiple_certs_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2)
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -noattr -outform DER -out $@
|
||||
$(OPENSSL) smime -sign -binary -in pkcs7_data.bin -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -noattr -outform DER -out $@
|
||||
all_final += pkcs7_data_multiple_certs_signed.der
|
||||
|
||||
# pkcs7 signature file with corrupted CERT
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,352 @@
|
||||
"""Common code for generating the test code to validate mbedtls_ssl_session_reset().
|
||||
"""
|
||||
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
|
||||
import enum
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import typing
|
||||
import argparse
|
||||
from typing import Dict, Iterator, List, Tuple, FrozenSet
|
||||
|
||||
from . import c_parsing_helper
|
||||
from . import typing_util
|
||||
from . import build_tree
|
||||
|
||||
class ResetBehavior(enum.Enum):
|
||||
KEEP = 0 # Kept unchanged before/after the reset
|
||||
RESET = 1 # Returned to the initial state (which is not necessarily 0)
|
||||
REALLOCATE = 2 # Pointer that gets reallocated
|
||||
IGNORE = 3 # Ignored field
|
||||
SPECIAL = 4
|
||||
|
||||
class ElementType(enum.Enum):
|
||||
SCALAR = 0
|
||||
POINTER = 1
|
||||
ARRAY = 2
|
||||
NAMED_STRUCTURE = 3
|
||||
IGNORE = 4
|
||||
SPECIAL = 5
|
||||
|
||||
class FieldsInfo(typing.NamedTuple):
|
||||
"""Expected reset behavior for the fields of the structure."""
|
||||
rules: Dict[str, ResetBehavior]
|
||||
special: Dict[str, List[str]]
|
||||
# The script isn't capable to identify named structures (ex: dtls_srtp_info)
|
||||
# so we keep an explicit list of them.
|
||||
named_structures: FrozenSet[str]
|
||||
|
||||
class CField():
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Information about one field of a C struct."""
|
||||
name: str
|
||||
conditional: List[str]
|
||||
element_type: ElementType
|
||||
|
||||
def __init__(self, name: str, conditionals: List[str], element_type: ElementType):
|
||||
self.name = name
|
||||
self.conditionals = conditionals.copy()
|
||||
self.element_type = element_type
|
||||
|
||||
def check_value(self) -> List[str]:
|
||||
raise Exception(f'Class {self.__class__.__name__} cannot handle entries'
|
||||
f'of type {self.element_type}')
|
||||
|
||||
class CFieldIgnore(CField):
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Explicitly ignored field."""
|
||||
def check_value(self) -> List[str]:
|
||||
return [f'/* {self.name} is ignored */']
|
||||
|
||||
class CFieldKeep(CField):
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Field kept unchanged."""
|
||||
def check_value(self) -> List[str]:
|
||||
if self.element_type == ElementType.SCALAR:
|
||||
return [f'TEST_EQUAL(before->{self.name}, after->{self.name});']
|
||||
elif self.element_type == ElementType.POINTER:
|
||||
return [f'TEST_ASSERT(before->{self.name} == after->{self.name});']
|
||||
elif self.element_type == ElementType.ARRAY:
|
||||
return [f'TEST_MEMORY_COMPARE(before->{self.name}, '
|
||||
f'sizeof(before->{self.name}), after->{self.name}, '
|
||||
f'sizeof(after->{self.name}));']
|
||||
elif self.element_type == ElementType.NAMED_STRUCTURE:
|
||||
return [f'TEST_MEMORY_COMPARE(&(before->{self.name}), '
|
||||
f'sizeof(before->{self.name}), &(after->{self.name}), '
|
||||
f'sizeof(after->{self.name}));']
|
||||
return super().check_value()
|
||||
|
||||
class CFieldReset(CField):
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Field returned to the intial state."""
|
||||
def check_value(self) -> List[str]:
|
||||
if (self.element_type == ElementType.SCALAR) or (self.element_type == ElementType.POINTER):
|
||||
return [f'TEST_ASSERT(after->{self.name} == initial.{self.name});']
|
||||
elif self.element_type == ElementType.ARRAY:
|
||||
return [f'TEST_MEMORY_COMPARE(after->{self.name}, '
|
||||
f'sizeof(after->{self.name}), initial.{self.name}, '
|
||||
f'sizeof(initial.{self.name}));']
|
||||
elif self.element_type == ElementType.NAMED_STRUCTURE:
|
||||
return [f'TEST_MEMORY_COMPARE(&(after->{self.name}), '
|
||||
f'sizeof(after->{self.name}), &(initial.{self.name}), '
|
||||
f'sizeof(initial.{self.name}));']
|
||||
return super().check_value()
|
||||
|
||||
class CFieldReallocate(CField):
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Pointer (might be) reallocated during reset."""
|
||||
def check_value(self) -> List[str]:
|
||||
if self.element_type == ElementType.POINTER:
|
||||
return [f'TEST_ASSERT(after->{self.name} != NULL);']
|
||||
return super().check_value()
|
||||
|
||||
class CFieldSpecial(CField):
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Field with a custom check."""
|
||||
custom_behavior: List[str]
|
||||
|
||||
def __init__(self, name: str, conditional: List[str], element_type: ElementType,
|
||||
custom_behavior: List[str]):
|
||||
self.custom_behavior = custom_behavior
|
||||
super().__init__(name, conditional, element_type)
|
||||
|
||||
def check_value(self) -> List[str]:
|
||||
return self.custom_behavior
|
||||
|
||||
class CStruct:
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Information about the fields of a C struct."""
|
||||
|
||||
_PREPROCESSOR_RE = re.compile(r'\s*#\s*(\w+)\s*(.*)')
|
||||
_STRUCT_RE = re.compile(r'struct\s+(\w+)\s*{')
|
||||
_FIELD_RE = re.compile(r'\s*([^;]+);')
|
||||
_PRIVATE_FIELD_RE = re.compile(r'MBEDTLS_PRIVATE\((\w+)\)')
|
||||
_BARE_FIELD_RE = re.compile(r'[\t *](\w+)\Z')
|
||||
_NON_BLANK_RE = re.compile(r'.*\S')
|
||||
|
||||
def _get_element_type(self, name: str, declaration: str) -> ElementType:
|
||||
"""Return structure field type based on either its name or the fact
|
||||
that it belongs to the list of special symbols/named structures"""
|
||||
# Check for fields with custom check rules
|
||||
if name in self.fields_info.special:
|
||||
return ElementType.SPECIAL
|
||||
# Check for named structures
|
||||
if name in self.fields_info.named_structures:
|
||||
return ElementType.NAMED_STRUCTURE
|
||||
# Check for pointer
|
||||
if '*' in declaration:
|
||||
return ElementType.POINTER
|
||||
# Check for array
|
||||
if '[' in declaration:
|
||||
return ElementType.ARRAY
|
||||
# If we get here then the field is a scalar
|
||||
return ElementType.SCALAR
|
||||
|
||||
def _parse_field(self, declaration: str, conditionals: List[str]) -> CField:
|
||||
"""Return the CField object describing the given field declaration."""
|
||||
# Note that this simplistic parsing finds fields in inline
|
||||
# sub-structs, unions and enums.
|
||||
m = self._PRIVATE_FIELD_RE.search(declaration)
|
||||
if not m:
|
||||
m = self._BARE_FIELD_RE.search(declaration)
|
||||
if not m:
|
||||
raise Exception(f'Field name not found in "{declaration}"')
|
||||
name = m.group(1)
|
||||
# Get the expected behavior on reset
|
||||
if name not in self.fields_info.rules:
|
||||
raise Exception(f'Field {name} does not have an associated behavior')
|
||||
behavior = self.fields_info.rules[name]
|
||||
element_type = self._get_element_type(name, declaration)
|
||||
if behavior == ResetBehavior.SPECIAL:
|
||||
return CFieldSpecial(name, conditionals, element_type,
|
||||
self.fields_info.special[name])
|
||||
elif behavior == ResetBehavior.KEEP:
|
||||
return CFieldKeep(name, conditionals, element_type)
|
||||
elif behavior == ResetBehavior.REALLOCATE:
|
||||
return CFieldReallocate(name, conditionals, element_type)
|
||||
elif behavior == ResetBehavior.IGNORE:
|
||||
return CFieldIgnore(name, conditionals, element_type)
|
||||
elif behavior == ResetBehavior.RESET:
|
||||
return CFieldReset(name, conditionals, element_type)
|
||||
else:
|
||||
raise Exception(f'Unhandled behavior {behavior}')
|
||||
|
||||
@staticmethod
|
||||
def _continue_parsing_preprocessor(arguments: str,
|
||||
lines: Iterator[Tuple[int, str]]) -> str:
|
||||
"""Append continuation lines of preprocesssor directive."""
|
||||
while True:
|
||||
try:
|
||||
line_content = next(lines)[1]
|
||||
arguments = arguments + '\n' + line_content
|
||||
except StopIteration:
|
||||
raise Exception('Unexpected end of file reached while '
|
||||
' parsing a C preprocessor directive')
|
||||
if not line_content.endswith('\\'):
|
||||
break
|
||||
return arguments
|
||||
|
||||
def _structure_fields(self,
|
||||
lines: Iterator[Tuple[int, str]],
|
||||
struct_name: str) -> Iterator[CField]:
|
||||
"""Yield a CField object for each field of the given structure."""
|
||||
# pylint: disable=too-many-branches
|
||||
found_start = False
|
||||
for num, line in lines:
|
||||
m = self._STRUCT_RE.match(line)
|
||||
if m and m.group(1) == struct_name:
|
||||
found_start = True
|
||||
break
|
||||
if not found_start:
|
||||
raise Exception(f'Definition of struct {struct_name} not found')
|
||||
conditionals: List[str] = []
|
||||
for num, line in lines:
|
||||
if line.startswith('}'):
|
||||
return
|
||||
m = self._PREPROCESSOR_RE.match(line)
|
||||
if m:
|
||||
# If the preprocessor directives are included in parentheses (ex:
|
||||
# "(defined(AAA) && defined(BBB))") then 'line' contains the full directive
|
||||
# including new lines (if present) so we can just copy that.
|
||||
# If instead outer parentheses are missing, ex: "defined(AAA) && defined(BBB)"
|
||||
# then parsing stops at the end of the line so we need to keep parsing
|
||||
# manually if there is a "\" at the end of the line.
|
||||
if line.endswith('\\'):
|
||||
arguments = m.group(2)
|
||||
arguments = self._continue_parsing_preprocessor(arguments, lines)
|
||||
one_conditional = '#if ' + arguments
|
||||
else:
|
||||
one_conditional = line
|
||||
one_conditional = one_conditional + '\n'
|
||||
directive = m.group(1)
|
||||
if directive == 'if':
|
||||
conditionals.append(one_conditional)
|
||||
elif directive == 'endif':
|
||||
del conditionals[-1]
|
||||
else:
|
||||
raise Exception(f'Unsupported directive #{directive} at line {num}')
|
||||
continue
|
||||
m = self._FIELD_RE.match(line)
|
||||
if m:
|
||||
yield self._parse_field(m.group(1), conditionals)
|
||||
continue
|
||||
m = self._NON_BLANK_RE.match(line)
|
||||
if m:
|
||||
raise Exception(f'Failed to parse non-empty line {num}. Content is: {line}')
|
||||
raise Exception(f'End of definition of struct {struct_name} not found')
|
||||
|
||||
def _check_special_fields(self):
|
||||
"""Ensure that all the entries FieldsInfo.rules that are given a SPECIAL
|
||||
behavior also have the corresponding entry in FieldsInfo.special
|
||||
(and viceversa)"""
|
||||
in_rules = frozenset(name for name in self.fields_info.rules
|
||||
if self.fields_info.rules[name] == ResetBehavior.SPECIAL)
|
||||
in_special = frozenset(self.fields_info.special)
|
||||
if in_rules != in_special:
|
||||
raise Exception(f'Fields with SPECIAL rule in FieldsInfo.rules but '
|
||||
f'not listed in FieldsInfo.special: {in_rules - in_special}. '
|
||||
f'Fields listed FieldsInfo.special, but not given a'
|
||||
f'SPECIAL rule in FieldsInfo.rules: {in_special - in_rules}.')
|
||||
|
||||
def _check_rules_struct_fields_matching(self):
|
||||
"""Ensure that for each field of the given FieldsInfo.rules there is
|
||||
an entry in the parsed C structure and viceversa"""
|
||||
given = frozenset(name for name in self.fields_info.rules)
|
||||
parsed = frozenset(field.name for field in self.fields)
|
||||
if given != parsed:
|
||||
raise Exception(f'Fields found in the C struct but not given a '
|
||||
f'reset behavior: {parsed - given}. '
|
||||
f'Fields given a reset behavior but not found in '
|
||||
f'the C struct: {given - parsed}')
|
||||
|
||||
def __init__(self, file_name: str, struct_name: str,
|
||||
fields_info: FieldsInfo) -> None:
|
||||
"""Parse a structure definition in a C source file."""
|
||||
self.fields_info = fields_info
|
||||
self._check_special_fields()
|
||||
lines = c_parsing_helper.read_logical_lines(file_name)
|
||||
self.fields = list(self._structure_fields(lines, struct_name))
|
||||
self._check_rules_struct_fields_matching()
|
||||
|
||||
|
||||
class SSLContextStruct(CStruct):
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Information about the fields of struct mbedtls_ssl_context."""
|
||||
|
||||
def __init__(self, fields_info: FieldsInfo) -> None:
|
||||
super().__init__('include/mbedtls/ssl.h', 'mbedtls_ssl_context',
|
||||
fields_info)
|
||||
|
||||
def write_check_function(self, out: typing_util.Writable) -> None:
|
||||
"""Write the generated context-checking function to the output."""
|
||||
out.write(f"""\
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following function was automatically generated through the script
|
||||
* {sys.argv[0]}.
|
||||
*/
|
||||
|
||||
#include <test/ssl_helpers.h>
|
||||
#include <test/ssl_helpers_internal.h>
|
||||
#include "mbedtls/psa_util.h"
|
||||
#include <test/macros.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
|
||||
int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context *before,
|
||||
const mbedtls_ssl_context *after)
|
||||
{{
|
||||
mbedtls_ssl_context initial;
|
||||
int ret = -1;
|
||||
|
||||
/* Create a freshly initialized SSL context*/
|
||||
memset(&initial, 0, sizeof(initial));
|
||||
mbedtls_ssl_init(&initial);
|
||||
TEST_EQUAL(mbedtls_ssl_setup(&initial, after->conf), 0);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
""")
|
||||
for field in self.fields:
|
||||
if len(field.conditionals) > 0:
|
||||
out.write('\n'.join(field.conditionals))
|
||||
for check_line in field.check_value():
|
||||
out.write(f' {check_line}\n')
|
||||
if len(field.conditionals) > 0:
|
||||
out.write('#endif\n' * len(field.conditionals))
|
||||
out.write(f"""\
|
||||
/* *INDENT-ON* */
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
mbedtls_ssl_free(&initial);
|
||||
|
||||
return ret;
|
||||
}}
|
||||
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
""")
|
||||
|
||||
|
||||
def main(fields_info: FieldsInfo):
|
||||
if not build_tree.looks_like_mbedtls_root(os.curdir):
|
||||
raise Exception("The script must be launched from the root path of Mbed TLS")
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument('-o', dest='output_file',
|
||||
help='Generated output file',
|
||||
default='tests/src/ssl_context_reset_verifier.c')
|
||||
parsed_args = arg_parser.parse_args()
|
||||
|
||||
output_file = parsed_args.output_file
|
||||
with open(output_file, 'wt') as out:
|
||||
ssl_context = SSLContextStruct(fields_info)
|
||||
ssl_context.write_check_function(out)
|
||||
Reference in New Issue
Block a user