mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-02-11 09:40:38 +00:00
Merge remote-tracking branch 'mbedtls-3.6' into test-cases-not-executed-enforce-3.6
Conflicts: * framework: update to the head of 'main'.
This commit is contained in:
commit
2d94866764
@ -107,7 +107,7 @@ The following branches are currently maintained:
|
||||
- [`development`](https://github.com/Mbed-TLS/mbedtls/)
|
||||
- [`mbedtls-3.6`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-3.6)
|
||||
maintained until March 2027, see
|
||||
<https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.1>.
|
||||
<https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.2>.
|
||||
- [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28)
|
||||
maintained until the end of 2024, see
|
||||
<https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.9>.
|
||||
|
@ -40,12 +40,12 @@ cmake_policy(SET CMP0012 NEW)
|
||||
if(TEST_CPP)
|
||||
project("Mbed TLS"
|
||||
LANGUAGES C CXX
|
||||
VERSION 3.6.1
|
||||
VERSION 3.6.2
|
||||
)
|
||||
else()
|
||||
project("Mbed TLS"
|
||||
LANGUAGES C
|
||||
VERSION 3.6.1
|
||||
VERSION 3.6.2
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -229,7 +229,15 @@ if(CMAKE_COMPILER_IS_GNU)
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -g3")
|
||||
set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage")
|
||||
set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
|
||||
# Old GCC versions hit a performance problem with test_suite_pkwrite
|
||||
# "Private keey write check EC" tests when building with Asan+UBSan
|
||||
# and -O3: those tests take more than 100x time than normal, with
|
||||
# test_suite_pkwrite taking >3h on the CI. Observed with GCC 5.4 on
|
||||
# Ubuntu 16.04 x86_64 and GCC 6.5 on Ubuntu 18.04 x86_64.
|
||||
# GCC 7.5 and above on Ubuntu 18.04 appear fine.
|
||||
# To avoid the performance problem, we use -O2 here. It doesn't slow
|
||||
# down much even with modern compiler versions.
|
||||
set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O2")
|
||||
set(CMAKE_C_FLAGS_ASANDBG "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
||||
set(CMAKE_C_FLAGS_TSAN "-fsanitize=thread -O3")
|
||||
set(CMAKE_C_FLAGS_TSANDBG "-fsanitize=thread -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
||||
@ -452,7 +460,7 @@ if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL)
|
||||
write_basic_package_version_file(
|
||||
"cmake/MbedTLSConfigVersion.cmake"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
VERSION 3.6.1)
|
||||
VERSION 3.6.2)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake"
|
||||
|
11
ChangeLog
11
ChangeLog
@ -1,5 +1,16 @@
|
||||
Mbed TLS ChangeLog (Sorted per branch, date)
|
||||
|
||||
= Mbed TLS 3.6.2 branch released 2024-10-14
|
||||
|
||||
Security
|
||||
* Fix a buffer underrun in mbedtls_pk_write_key_der() when
|
||||
called on an opaque key, MBEDTLS_USE_PSA_CRYPTO is enabled,
|
||||
and the output buffer is smaller than the actual output.
|
||||
Fix a related buffer underrun in mbedtls_pk_write_key_pem()
|
||||
when called on an opaque RSA key, MBEDTLS_USE_PSA_CRYPTO is enabled
|
||||
and MBEDTLS_MPI_MAX_SIZE is smaller than needed for a 4096-bit RSA key.
|
||||
CVE-2024-49195
|
||||
|
||||
= Mbed TLS 3.6.1 branch released 2024-08-30
|
||||
|
||||
API changes
|
||||
|
3
ChangeLog.d/fix-driver-schema-check.txt
Normal file
3
ChangeLog.d/fix-driver-schema-check.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Bugfix
|
||||
* Fix invalid JSON schemas for driver descriptions used by
|
||||
generate_driver_wrappers.py.
|
@ -67,7 +67,7 @@ Note that a slot must not be moved in memory while it is being read or written.
|
||||
There are three variants of the key store implementation, responding to different needs.
|
||||
|
||||
* Hybrid key store ([static key slots](#static-key-store) with dynamic key data): the key store is a statically allocated array of slots, of size `MBEDTLS_PSA_KEY_SLOT_COUNT`. Key material is allocated on the heap. This is the historical implementation. It remains the default in the Mbed TLS 3.6 long-time support (LTS) branch when using a handwritten `mbedtls_config.h`, as is common on resource-constrained platforms, because the alternatives have tradeoffs (key size limit and larger RAM usage at rest for the static key store, larger code size and more risk due to code complexity for the dynamic key store).
|
||||
* Fully [static key store](#static-key-store) (since Mbed TLS 3.6.2): the key store is a statically allocated array of slots, of size `MBEDTLS_PSA_KEY_SLOT_COUNT`. Each key slot contains the key representation directly, and the key representation must be no more than `MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE` bytes. This is intended for very constrained devices that do not have a heap.
|
||||
* Fully [static key store](#static-key-store) (since Mbed TLS 3.6.3): the key store is a statically allocated array of slots, of size `MBEDTLS_PSA_KEY_SLOT_COUNT`. Each key slot contains the key representation directly, and the key representation must be no more than `MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE` bytes. This is intended for very constrained devices that do not have a heap.
|
||||
* [Dynamic key store](#dynamic-key-store) (since Mbed TLS 3.6.1): the key store is dynamically allocated as multiple slices on the heap, with a size that adjusts to the application's usage. Key material is allocated on the heap. Compared to the hybrid key store, the code size and RAM consumption are larger. This is intended for higher-end devices where applications are not expected to have a highly predicatable resource usage. This is the default implementation when using the default `mbedtls_config.h` file, as is common on platforms such as Linux, starting with Mbed TLS 3.6.1.
|
||||
|
||||
#### Future improvement: merging the key store variants
|
||||
@ -95,7 +95,7 @@ When creating a volatile key, the slice containing the slot and index of the slo
|
||||
|
||||
The static key store is the historical implementation. The key store is a statically allocated array of slots, of size `MBEDTLS_PSA_KEY_SLOT_COUNT`. This value is an upper bound for the total number of volatile keys plus loaded keys.
|
||||
|
||||
Since Mbed TLS 3.6.2, there are two variants for the static key store: a hybrid variant (default), and a fully-static variant enabled by the configuration option `MBEDTLS_PSA_STATIC_KEY_SLOTS`. The two variants have the same key store management: the only difference is in how the memory for key data is managed. With fully static key slots, the key data is directly inside the slot, and limited to `MBEDTLS_PSA_KEY_SLOT_BUFFER_SIZE` bytes. With the hybrid key store, the slot contains a pointer to the key data, which is allocated on the heap.
|
||||
Since Mbed TLS 3.6.3, there are two variants for the static key store: a hybrid variant (default), and a fully-static variant enabled by the configuration option `MBEDTLS_PSA_STATIC_KEY_SLOTS`. The two variants have the same key store management: the only difference is in how the memory for key data is managed. With fully static key slots, the key data is directly inside the slot, and limited to `MBEDTLS_PSA_KEY_SLOT_BUFFER_SIZE` bytes. With the hybrid key store, the slot contains a pointer to the key data, which is allocated on the heap.
|
||||
|
||||
#### Volatile key identifiers in the static key store
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage Mbed TLS v3.6.1 API Documentation
|
||||
* @mainpage Mbed TLS v3.6.2 API Documentation
|
||||
*
|
||||
* This documentation describes the internal structure of Mbed TLS. It was
|
||||
* automatically generated from specially formatted comment blocks in
|
||||
|
@ -1,4 +1,4 @@
|
||||
PROJECT_NAME = "Mbed TLS v3.6.1"
|
||||
PROJECT_NAME = "Mbed TLS v3.6.2"
|
||||
OUTPUT_DIRECTORY = ../apidoc/
|
||||
FULL_PATH_NAMES = NO
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
|
@ -26,16 +26,16 @@
|
||||
*/
|
||||
#define MBEDTLS_VERSION_MAJOR 3
|
||||
#define MBEDTLS_VERSION_MINOR 6
|
||||
#define MBEDTLS_VERSION_PATCH 1
|
||||
#define MBEDTLS_VERSION_PATCH 2
|
||||
|
||||
/**
|
||||
* The single version number has the following structure:
|
||||
* MMNNPP00
|
||||
* Major version | Minor version | Patch version
|
||||
*/
|
||||
#define MBEDTLS_VERSION_NUMBER 0x03060100
|
||||
#define MBEDTLS_VERSION_STRING "3.6.1"
|
||||
#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.1"
|
||||
#define MBEDTLS_VERSION_NUMBER 0x03060200
|
||||
#define MBEDTLS_VERSION_STRING "3.6.2"
|
||||
#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.2"
|
||||
|
||||
/* Macros for build-time platform detection */
|
||||
|
||||
|
@ -166,11 +166,11 @@ if(GEN_FILES)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ssl_debug_helpers_generated.c
|
||||
COMMAND
|
||||
${MBEDTLS_PYTHON_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ssl_debug_helpers.py
|
||||
--mbedtls-root ${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ssl_debug_helpers.py
|
||||
${error_headers}
|
||||
)
|
||||
|
||||
@ -300,7 +300,7 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
|
||||
if(USE_SHARED_MBEDTLS_LIBRARY)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_library(${mbedcrypto_target} SHARED ${src_crypto})
|
||||
set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.6.1 SOVERSION 16)
|
||||
set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.6.2 SOVERSION 16)
|
||||
target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
|
||||
|
||||
if(TARGET ${everest_target})
|
||||
@ -312,11 +312,11 @@ if(USE_SHARED_MBEDTLS_LIBRARY)
|
||||
endif()
|
||||
|
||||
add_library(${mbedx509_target} SHARED ${src_x509})
|
||||
set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.6.1 SOVERSION 7)
|
||||
set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.6.2 SOVERSION 7)
|
||||
target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
|
||||
|
||||
add_library(${mbedtls_target} SHARED ${src_tls})
|
||||
set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.6.1 SOVERSION 21)
|
||||
set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.6.2 SOVERSION 21)
|
||||
target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
|
||||
endif(USE_SHARED_MBEDTLS_LIBRARY)
|
||||
|
||||
|
@ -355,11 +355,11 @@ error.c:
|
||||
echo " Gen $@"
|
||||
$(PERL) ../scripts/generate_errors.pl
|
||||
|
||||
ssl_debug_helpers_generated.c: $(gen_file_dep) ../scripts/generate_ssl_debug_helpers.py
|
||||
ssl_debug_helpers_generated.c: $(gen_file_dep) ../framework/scripts/generate_ssl_debug_helpers.py
|
||||
ssl_debug_helpers_generated.c: $(gen_file_dep) $(filter-out %config%,$(wildcard ../include/mbedtls/*.h))
|
||||
ssl_debug_helpers_generated.c:
|
||||
echo " Gen $@"
|
||||
$(PYTHON) ../scripts/generate_ssl_debug_helpers.py --mbedtls-root .. .
|
||||
$(PYTHON) ../framework/scripts/generate_ssl_debug_helpers.py --mbedtls-root .. .
|
||||
|
||||
version_features.c: $(gen_file_dep) ../scripts/generate_features.pl
|
||||
version_features.c: $(gen_file_dep) ../scripts/data_files/version_features.fmt
|
||||
|
@ -65,17 +65,21 @@ static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
|
||||
uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
|
||||
size_t len = 0, tmp_len = 0;
|
||||
size_t tmp_len = 0;
|
||||
|
||||
if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
}
|
||||
/* Ensure there's enough space in the provided buffer before copying data into it. */
|
||||
if (tmp_len > (size_t) (*p - buf)) {
|
||||
mbedtls_platform_zeroize(tmp, sizeof(tmp));
|
||||
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
||||
}
|
||||
*p -= tmp_len;
|
||||
memcpy(*p, tmp, tmp_len);
|
||||
len += tmp_len;
|
||||
mbedtls_platform_zeroize(tmp, sizeof(tmp));
|
||||
|
||||
return (int) len;
|
||||
return (int) tmp_len;
|
||||
}
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
|
||||
@ -125,6 +129,10 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
|
||||
if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
|
||||
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
|
||||
}
|
||||
/* Ensure there's enough space in the provided buffer before copying data into it. */
|
||||
if (len > (size_t) (*p - start)) {
|
||||
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
||||
}
|
||||
*p -= len;
|
||||
memcpy(*p, buf, len);
|
||||
return (int) len;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define MBEDTLS_SSL_MISC_H
|
||||
|
||||
#include "mbedtls/build_info.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
@ -47,7 +48,7 @@
|
||||
#include "ssl_ciphersuites_internal.h"
|
||||
#include "x509_internal.h"
|
||||
#include "pk_internal.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/* Shorthand for restartable ECC */
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
|
||||
|
@ -102,8 +102,10 @@ def get_src_files(since: Optional[str]) -> List[str]:
|
||||
"--name-only", "--pretty=", "--"] + src_files
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
committed_changed_files = output.split()
|
||||
|
||||
# ... the framework submodule
|
||||
cmd = ["git", "-C", "framework", "log", since + "..HEAD",
|
||||
framework_since = get_submodule_hash(since, "framework")
|
||||
cmd = ["git", "-C", "framework", "log", framework_since + "..HEAD",
|
||||
"--name-only", "--pretty=", "--"] + framework_src_files
|
||||
output = subprocess.check_output(cmd, universal_newlines=True,
|
||||
env=framework_env)
|
||||
@ -135,6 +137,12 @@ def get_src_files(since: Optional[str]) -> List[str]:
|
||||
is_file_autogenerated(filename))]
|
||||
return src_files
|
||||
|
||||
def get_submodule_hash(commit: str, submodule: str) -> str:
|
||||
"""Get the commit hash of a submodule at a given commit in the Git repository."""
|
||||
cmd = ["git", "ls-tree", commit, submodule]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
return output.split()[2]
|
||||
|
||||
def get_uncrustify_version() -> str:
|
||||
"""
|
||||
Get the version string from Uncrustify
|
||||
|
@ -11,7 +11,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": ["opaque"]
|
||||
"const": "opaque"
|
||||
},
|
||||
"location": {
|
||||
"type": ["integer","string"],
|
||||
|
@ -11,7 +11,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": ["transparent"]
|
||||
"const": "transparent"
|
||||
},
|
||||
"mbedtls/h_condition": {
|
||||
"type": "string"
|
||||
|
@ -1,416 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Generate library/ssl_debug_helpers_generated.c
|
||||
|
||||
The code generated by this module includes debug helper functions that can not be
|
||||
implemented by fixed codes.
|
||||
|
||||
"""
|
||||
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import textwrap
|
||||
import argparse
|
||||
|
||||
import framework_scripts_path # pylint: disable=unused-import
|
||||
from mbedtls_framework import build_tree
|
||||
|
||||
|
||||
def remove_c_comments(string):
|
||||
"""
|
||||
Remove C style comments from input string
|
||||
"""
|
||||
string_pattern = r"(?P<string>\".*?\"|\'.*?\')"
|
||||
comment_pattern = r"(?P<comment>/\*.*?\*/|//[^\r\n]*$)"
|
||||
pattern = re.compile(string_pattern + r'|' + comment_pattern,
|
||||
re.MULTILINE | re.DOTALL)
|
||||
|
||||
def replacer(match):
|
||||
if match.lastgroup == 'comment':
|
||||
return ""
|
||||
return match.group()
|
||||
return pattern.sub(replacer, string)
|
||||
|
||||
|
||||
class CondDirectiveNotMatch(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def preprocess_c_source_code(source, *classes):
|
||||
"""
|
||||
Simple preprocessor for C source code.
|
||||
|
||||
Only processes condition directives without expanding them.
|
||||
Yield object according to the classes input. Most match firstly
|
||||
|
||||
If the directive pair does not match , raise CondDirectiveNotMatch.
|
||||
|
||||
Assume source code does not include comments and compile pass.
|
||||
|
||||
"""
|
||||
|
||||
pattern = re.compile(r"^[ \t]*#[ \t]*" +
|
||||
r"(?P<directive>(if[ \t]|ifndef[ \t]|ifdef[ \t]|else|endif))" +
|
||||
r"[ \t]*(?P<param>(.*\\\n)*.*$)",
|
||||
re.MULTILINE)
|
||||
stack = []
|
||||
|
||||
def _yield_objects(s, d, p, st, end):
|
||||
"""
|
||||
Output matched source piece
|
||||
"""
|
||||
nonlocal stack
|
||||
start_line, end_line = '', ''
|
||||
if stack:
|
||||
start_line = '#{} {}'.format(d, p)
|
||||
if d == 'if':
|
||||
end_line = '#endif /* {} */'.format(p)
|
||||
elif d == 'ifdef':
|
||||
end_line = '#endif /* defined({}) */'.format(p)
|
||||
else:
|
||||
end_line = '#endif /* !defined({}) */'.format(p)
|
||||
has_instance = False
|
||||
for cls in classes:
|
||||
for instance in cls.extract(s, st, end):
|
||||
if has_instance is False:
|
||||
has_instance = True
|
||||
yield pair_start, start_line
|
||||
yield instance.span()[0], instance
|
||||
if has_instance:
|
||||
yield start, end_line
|
||||
|
||||
for match in pattern.finditer(source):
|
||||
|
||||
directive = match.groupdict()['directive'].strip()
|
||||
param = match.groupdict()['param']
|
||||
start, end = match.span()
|
||||
|
||||
if directive in ('if', 'ifndef', 'ifdef'):
|
||||
stack.append((directive, param, start, end))
|
||||
continue
|
||||
|
||||
if not stack:
|
||||
raise CondDirectiveNotMatch()
|
||||
|
||||
pair_directive, pair_param, pair_start, pair_end = stack.pop()
|
||||
yield from _yield_objects(source,
|
||||
pair_directive,
|
||||
pair_param,
|
||||
pair_end,
|
||||
start)
|
||||
|
||||
if directive == 'endif':
|
||||
continue
|
||||
|
||||
if pair_directive == 'if':
|
||||
directive = 'if'
|
||||
param = "!( {} )".format(pair_param)
|
||||
elif pair_directive == 'ifdef':
|
||||
directive = 'ifndef'
|
||||
param = pair_param
|
||||
else:
|
||||
directive = 'ifdef'
|
||||
param = pair_param
|
||||
|
||||
stack.append((directive, param, start, end))
|
||||
assert not stack, len(stack)
|
||||
|
||||
|
||||
class EnumDefinition:
|
||||
"""
|
||||
Generate helper functions around enumeration.
|
||||
|
||||
Currently, it generate translation function from enum value to string.
|
||||
Enum definition looks like:
|
||||
[typedef] enum [prefix name] { [body] } [suffix name];
|
||||
|
||||
Known limitation:
|
||||
- the '}' and ';' SHOULD NOT exist in different macro blocks. Like
|
||||
```
|
||||
enum test {
|
||||
....
|
||||
#if defined(A)
|
||||
....
|
||||
};
|
||||
#else
|
||||
....
|
||||
};
|
||||
#endif
|
||||
```
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def extract(cls, source_code, start=0, end=-1):
|
||||
enum_pattern = re.compile(r'enum\s*(?P<prefix_name>\w*)\s*' +
|
||||
r'{\s*(?P<body>[^}]*)}' +
|
||||
r'\s*(?P<suffix_name>\w*)\s*;',
|
||||
re.MULTILINE | re.DOTALL)
|
||||
|
||||
for match in enum_pattern.finditer(source_code, start, end):
|
||||
yield EnumDefinition(source_code,
|
||||
span=match.span(),
|
||||
group=match.groupdict())
|
||||
|
||||
def __init__(self, source_code, span=None, group=None):
|
||||
assert isinstance(group, dict)
|
||||
prefix_name = group.get('prefix_name', None)
|
||||
suffix_name = group.get('suffix_name', None)
|
||||
body = group.get('body', None)
|
||||
assert prefix_name or suffix_name
|
||||
assert body
|
||||
assert span
|
||||
# If suffix_name exists, it is a typedef
|
||||
self._prototype = suffix_name if suffix_name else 'enum ' + prefix_name
|
||||
self._name = suffix_name if suffix_name else prefix_name
|
||||
self._body = body
|
||||
self._source = source_code
|
||||
self._span = span
|
||||
|
||||
def __repr__(self):
|
||||
return 'Enum({},{})'.format(self._name, self._span)
|
||||
|
||||
def __str__(self):
|
||||
return repr(self)
|
||||
|
||||
def span(self):
|
||||
return self._span
|
||||
|
||||
def generate_translation_function(self):
|
||||
"""
|
||||
Generate function for translating value to string
|
||||
"""
|
||||
translation_table = []
|
||||
|
||||
for line in self._body.splitlines():
|
||||
|
||||
if line.strip().startswith('#'):
|
||||
# Preprocess directive, keep it in table
|
||||
translation_table.append(line.strip())
|
||||
continue
|
||||
|
||||
if not line.strip():
|
||||
continue
|
||||
|
||||
for field in line.strip().split(','):
|
||||
if not field.strip():
|
||||
continue
|
||||
member = field.strip().split()[0]
|
||||
translation_table.append(
|
||||
'{space}case {member}:\n{space} return "{member}";'
|
||||
.format(member=member, space=' '*8)
|
||||
)
|
||||
|
||||
body = textwrap.dedent('''\
|
||||
const char *{name}_str( {prototype} in )
|
||||
{{
|
||||
switch (in) {{
|
||||
{translation_table}
|
||||
default:
|
||||
return "UNKNOWN_VALUE";
|
||||
}}
|
||||
}}
|
||||
''')
|
||||
body = body.format(translation_table='\n'.join(translation_table),
|
||||
name=self._name,
|
||||
prototype=self._prototype)
|
||||
return body
|
||||
|
||||
|
||||
class SignatureAlgorithmDefinition:
|
||||
"""
|
||||
Generate helper functions for signature algorithms.
|
||||
|
||||
It generates translation function from signature algorithm define to string.
|
||||
Signature algorithm definition looks like:
|
||||
#define MBEDTLS_TLS1_3_SIG_[ upper case signature algorithm ] [ value(hex) ]
|
||||
|
||||
Known limitation:
|
||||
- the definitions SHOULD exist in same macro blocks.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def extract(cls, source_code, start=0, end=-1):
|
||||
sig_alg_pattern = re.compile(r'#define\s+(?P<name>MBEDTLS_TLS1_3_SIG_\w+)\s+' +
|
||||
r'(?P<value>0[xX][0-9a-fA-F]+)$',
|
||||
re.MULTILINE | re.DOTALL)
|
||||
matches = list(sig_alg_pattern.finditer(source_code, start, end))
|
||||
if matches:
|
||||
yield SignatureAlgorithmDefinition(source_code, definitions=matches)
|
||||
|
||||
def __init__(self, source_code, definitions=None):
|
||||
if definitions is None:
|
||||
definitions = []
|
||||
assert isinstance(definitions, list) and definitions
|
||||
self._definitions = definitions
|
||||
self._source = source_code
|
||||
|
||||
def __repr__(self):
|
||||
return 'SigAlgs({})'.format(self._definitions[0].span())
|
||||
|
||||
def span(self):
|
||||
return self._definitions[0].span()
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Generate function for translating value to string
|
||||
"""
|
||||
translation_table = []
|
||||
for m in self._definitions:
|
||||
name = m.groupdict()['name']
|
||||
return_val = name[len('MBEDTLS_TLS1_3_SIG_'):].lower()
|
||||
translation_table.append(
|
||||
' case {}:\n return "{}";'.format(name, return_val))
|
||||
|
||||
body = textwrap.dedent('''\
|
||||
const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
|
||||
{{
|
||||
switch( in )
|
||||
{{
|
||||
{translation_table}
|
||||
}};
|
||||
|
||||
return "UNKNOWN";
|
||||
}}''')
|
||||
body = body.format(translation_table='\n'.join(translation_table))
|
||||
return body
|
||||
|
||||
|
||||
class NamedGroupDefinition:
|
||||
"""
|
||||
Generate helper functions for named group
|
||||
|
||||
It generates translation function from named group define to string.
|
||||
Named group definition looks like:
|
||||
#define MBEDTLS_SSL_IANA_TLS_GROUP_[ upper case named group ] [ value(hex) ]
|
||||
|
||||
Known limitation:
|
||||
- the definitions SHOULD exist in same macro blocks.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def extract(cls, source_code, start=0, end=-1):
|
||||
named_group_pattern = re.compile(r'#define\s+(?P<name>MBEDTLS_SSL_IANA_TLS_GROUP_\w+)\s+' +
|
||||
r'(?P<value>0[xX][0-9a-fA-F]+)$',
|
||||
re.MULTILINE | re.DOTALL)
|
||||
matches = list(named_group_pattern.finditer(source_code, start, end))
|
||||
if matches:
|
||||
yield NamedGroupDefinition(source_code, definitions=matches)
|
||||
|
||||
def __init__(self, source_code, definitions=None):
|
||||
if definitions is None:
|
||||
definitions = []
|
||||
assert isinstance(definitions, list) and definitions
|
||||
self._definitions = definitions
|
||||
self._source = source_code
|
||||
|
||||
def __repr__(self):
|
||||
return 'NamedGroup({})'.format(self._definitions[0].span())
|
||||
|
||||
def span(self):
|
||||
return self._definitions[0].span()
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Generate function for translating value to string
|
||||
"""
|
||||
translation_table = []
|
||||
for m in self._definitions:
|
||||
name = m.groupdict()['name']
|
||||
iana_name = name[len('MBEDTLS_SSL_IANA_TLS_GROUP_'):].lower()
|
||||
translation_table.append(' case {}:\n return "{}";'.format(name, iana_name))
|
||||
|
||||
body = textwrap.dedent('''\
|
||||
const char *mbedtls_ssl_named_group_to_str( uint16_t in )
|
||||
{{
|
||||
switch( in )
|
||||
{{
|
||||
{translation_table}
|
||||
}};
|
||||
|
||||
return "UNKNOWN";
|
||||
}}''')
|
||||
body = body.format(translation_table='\n'.join(translation_table))
|
||||
return body
|
||||
|
||||
|
||||
OUTPUT_C_TEMPLATE = '''\
|
||||
/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */
|
||||
|
||||
/**
|
||||
* \\file ssl_debug_helpers_generated.c
|
||||
*
|
||||
* \\brief Automatically generated helper functions for debugging
|
||||
*/
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
|
||||
#include "ssl_debug_helpers.h"
|
||||
|
||||
{functions}
|
||||
|
||||
#endif /* MBEDTLS_DEBUG_C */
|
||||
/* End of automatically generated file. */
|
||||
|
||||
'''
|
||||
|
||||
|
||||
def generate_ssl_debug_helpers(output_directory, mbedtls_root):
|
||||
"""
|
||||
Generate functions of debug helps
|
||||
"""
|
||||
mbedtls_root = os.path.abspath(
|
||||
mbedtls_root or build_tree.guess_mbedtls_root())
|
||||
with open(os.path.join(mbedtls_root, 'include/mbedtls/ssl.h')) as f:
|
||||
source_code = remove_c_comments(f.read())
|
||||
|
||||
definitions = dict()
|
||||
for start, instance in preprocess_c_source_code(source_code,
|
||||
EnumDefinition,
|
||||
SignatureAlgorithmDefinition,
|
||||
NamedGroupDefinition):
|
||||
if start in definitions:
|
||||
continue
|
||||
if isinstance(instance, EnumDefinition):
|
||||
definition = instance.generate_translation_function()
|
||||
else:
|
||||
definition = instance
|
||||
definitions[start] = definition
|
||||
|
||||
function_definitions = [str(v) for _, v in sorted(definitions.items())]
|
||||
if output_directory == sys.stdout:
|
||||
sys.stdout.write(OUTPUT_C_TEMPLATE.format(
|
||||
functions='\n'.join(function_definitions)))
|
||||
else:
|
||||
with open(os.path.join(output_directory, 'ssl_debug_helpers_generated.c'), 'w') as f:
|
||||
f.write(OUTPUT_C_TEMPLATE.format(
|
||||
functions='\n'.join(function_definitions)))
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Command line entry
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--mbedtls-root', nargs='?', default=None,
|
||||
help='root directory of mbedtls source code')
|
||||
parser.add_argument('output_directory', nargs='?',
|
||||
default='library', help='source/header files location')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
generate_ssl_debug_helpers(args.output_directory, args.mbedtls_root)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
@ -13,7 +13,7 @@ python scripts\generate_driver_wrappers.py || exit /b 1
|
||||
perl scripts\generate_errors.pl || exit /b 1
|
||||
perl scripts\generate_query_config.pl || exit /b 1
|
||||
perl scripts\generate_features.pl || exit /b 1
|
||||
python scripts\generate_ssl_debug_helpers.py || exit /b 1
|
||||
python framework\scripts\generate_ssl_debug_helpers.py || exit /b 1
|
||||
|
||||
@rem @@@@ Build @@@@
|
||||
perl scripts\generate_visualc_files.pl || exit /b 1
|
||||
@ -28,4 +28,4 @@ python framework\scripts\generate_ecp_tests.py || exit /b 1
|
||||
python framework\scripts\generate_psa_tests.py || exit /b 1
|
||||
python framework\scripts\generate_test_keys.py --output tests\src\test_keys.h || exit /b 1
|
||||
python framework\scripts\generate_test_cert_macros.py --output tests\src\test_certs.h || exit /b 1
|
||||
python tests\scripts\generate_tls13_compat_tests.py || exit /b 1
|
||||
python framework\scripts\generate_tls13_compat_tests.py || exit /b 1
|
||||
|
@ -170,9 +170,9 @@ if(GEN_FILES)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
COMMAND
|
||||
"${MBEDTLS_PYTHON_EXECUTABLE}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_tls13_compat_tests.py"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls13_compat_tests.py"
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_tls13_compat_tests.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls13_compat_tests.py
|
||||
)
|
||||
add_custom_target(tls13-compat.sh
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/tls13-compat.sh)
|
||||
|
@ -58,9 +58,9 @@ GENERATED_FILES += src/test_keys.h src/test_certs.h
|
||||
# Generated files needed to (fully) run ssl-opt.sh
|
||||
.PHONY: ssl-opt
|
||||
|
||||
opt-testcases/tls13-compat.sh: scripts/generate_tls13_compat_tests.py
|
||||
opt-testcases/tls13-compat.sh: ../framework/scripts/generate_tls13_compat_tests.py
|
||||
echo " Gen $@"
|
||||
$(PYTHON) scripts/generate_tls13_compat_tests.py -o $@
|
||||
$(PYTHON) ../framework/scripts/generate_tls13_compat_tests.py -o $@
|
||||
GENERATED_FILES += opt-testcases/tls13-compat.sh
|
||||
ssl-opt: opt-testcases/tls13-compat.sh
|
||||
|
||||
|
@ -290,7 +290,7 @@ reset_ciphersuites()
|
||||
# list of entries of the form "STANDARD_NAME=PROGRAM_NAME".
|
||||
translate_ciphers()
|
||||
{
|
||||
ciphers=$(scripts/translate_ciphers.py "$@")
|
||||
ciphers=$(../framework/scripts/translate_ciphers.py "$@")
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "translate_ciphers.py failed with exit code $1" >&2
|
||||
echo "$2" >&2
|
||||
|
@ -140,8 +140,8 @@ if in_mbedtls_repo; then
|
||||
check scripts/generate_errors.pl library/error.c
|
||||
check scripts/generate_query_config.pl programs/test/query_config.c
|
||||
check scripts/generate_features.pl library/version_features.c
|
||||
check scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.c
|
||||
check tests/scripts/generate_tls13_compat_tests.py tests/opt-testcases/tls13-compat.sh
|
||||
check framework/scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.c
|
||||
check framework/scripts/generate_tls13_compat_tests.py tests/opt-testcases/tls13-compat.sh
|
||||
check framework/scripts/generate_test_cert_macros.py tests/src/test_certs.h
|
||||
# generate_visualc_files enumerates source files (library/*.c). It doesn't
|
||||
# care about their content, but the files must exist. So it must run after
|
||||
|
@ -157,6 +157,6 @@ component_check_test_helpers () {
|
||||
./framework/scripts/test_generate_test_code.py 2>&1
|
||||
|
||||
msg "unit test: translate_ciphers.py"
|
||||
python3 -m unittest tests/scripts/translate_ciphers.py 2>&1
|
||||
python3 -m unittest framework/scripts/translate_ciphers.py 2>&1
|
||||
}
|
||||
|
||||
|
@ -1,649 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# generate_tls13_compat_tests.py
|
||||
#
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
Generate TLSv1.3 Compat test cases
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import itertools
|
||||
from collections import namedtuple
|
||||
|
||||
# define certificates configuration entry
|
||||
Certificate = namedtuple("Certificate", ['cafile', 'certfile', 'keyfile'])
|
||||
# define the certificate parameters for signature algorithms
|
||||
CERTIFICATES = {
|
||||
'ecdsa_secp256r1_sha256': Certificate('$DATA_FILES_PATH/test-ca2.crt',
|
||||
'$DATA_FILES_PATH/ecdsa_secp256r1.crt',
|
||||
'$DATA_FILES_PATH/ecdsa_secp256r1.key'),
|
||||
'ecdsa_secp384r1_sha384': Certificate('$DATA_FILES_PATH/test-ca2.crt',
|
||||
'$DATA_FILES_PATH/ecdsa_secp384r1.crt',
|
||||
'$DATA_FILES_PATH/ecdsa_secp384r1.key'),
|
||||
'ecdsa_secp521r1_sha512': Certificate('$DATA_FILES_PATH/test-ca2.crt',
|
||||
'$DATA_FILES_PATH/ecdsa_secp521r1.crt',
|
||||
'$DATA_FILES_PATH/ecdsa_secp521r1.key'),
|
||||
'rsa_pss_rsae_sha256': Certificate('$DATA_FILES_PATH/test-ca_cat12.crt',
|
||||
'$DATA_FILES_PATH/server2-sha256.crt',
|
||||
'$DATA_FILES_PATH/server2.key')
|
||||
}
|
||||
|
||||
CIPHER_SUITE_IANA_VALUE = {
|
||||
"TLS_AES_128_GCM_SHA256": 0x1301,
|
||||
"TLS_AES_256_GCM_SHA384": 0x1302,
|
||||
"TLS_CHACHA20_POLY1305_SHA256": 0x1303,
|
||||
"TLS_AES_128_CCM_SHA256": 0x1304,
|
||||
"TLS_AES_128_CCM_8_SHA256": 0x1305
|
||||
}
|
||||
|
||||
SIG_ALG_IANA_VALUE = {
|
||||
"ecdsa_secp256r1_sha256": 0x0403,
|
||||
"ecdsa_secp384r1_sha384": 0x0503,
|
||||
"ecdsa_secp521r1_sha512": 0x0603,
|
||||
'rsa_pss_rsae_sha256': 0x0804,
|
||||
}
|
||||
|
||||
NAMED_GROUP_IANA_VALUE = {
|
||||
'secp256r1': 0x17,
|
||||
'secp384r1': 0x18,
|
||||
'secp521r1': 0x19,
|
||||
'x25519': 0x1d,
|
||||
'x448': 0x1e,
|
||||
# Only one finite field group to keep testing time within reasonable bounds.
|
||||
'ffdhe2048': 0x100,
|
||||
}
|
||||
|
||||
class TLSProgram:
|
||||
"""
|
||||
Base class for generate server/client command.
|
||||
"""
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def __init__(self, ciphersuite=None, signature_algorithm=None, named_group=None,
|
||||
cert_sig_alg=None):
|
||||
self._ciphers = []
|
||||
self._sig_algs = []
|
||||
self._named_groups = []
|
||||
self._cert_sig_algs = []
|
||||
if ciphersuite:
|
||||
self.add_ciphersuites(ciphersuite)
|
||||
if named_group:
|
||||
self.add_named_groups(named_group)
|
||||
if signature_algorithm:
|
||||
self.add_signature_algorithms(signature_algorithm)
|
||||
if cert_sig_alg:
|
||||
self.add_cert_signature_algorithms(cert_sig_alg)
|
||||
|
||||
# add_ciphersuites should not override by sub class
|
||||
def add_ciphersuites(self, *ciphersuites):
|
||||
self._ciphers.extend(
|
||||
[cipher for cipher in ciphersuites if cipher not in self._ciphers])
|
||||
|
||||
# add_signature_algorithms should not override by sub class
|
||||
def add_signature_algorithms(self, *signature_algorithms):
|
||||
self._sig_algs.extend(
|
||||
[sig_alg for sig_alg in signature_algorithms if sig_alg not in self._sig_algs])
|
||||
|
||||
# add_named_groups should not override by sub class
|
||||
def add_named_groups(self, *named_groups):
|
||||
self._named_groups.extend(
|
||||
[named_group for named_group in named_groups if named_group not in self._named_groups])
|
||||
|
||||
# add_cert_signature_algorithms should not override by sub class
|
||||
def add_cert_signature_algorithms(self, *signature_algorithms):
|
||||
self._cert_sig_algs.extend(
|
||||
[sig_alg for sig_alg in signature_algorithms if sig_alg not in self._cert_sig_algs])
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def pre_checks(self):
|
||||
return []
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def cmd(self):
|
||||
if not self._cert_sig_algs:
|
||||
self._cert_sig_algs = list(CERTIFICATES.keys())
|
||||
return self.pre_cmd()
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def post_checks(self):
|
||||
return []
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def pre_cmd(self):
|
||||
return ['false']
|
||||
|
||||
# pylint: disable=unused-argument,no-self-use
|
||||
def hrr_post_checks(self, named_group):
|
||||
return []
|
||||
|
||||
|
||||
class OpenSSLBase(TLSProgram):
|
||||
"""
|
||||
Generate base test commands for OpenSSL.
|
||||
"""
|
||||
|
||||
NAMED_GROUP = {
|
||||
'secp256r1': 'P-256',
|
||||
'secp384r1': 'P-384',
|
||||
'secp521r1': 'P-521',
|
||||
'x25519': 'X25519',
|
||||
'x448': 'X448',
|
||||
'ffdhe2048': 'ffdhe2048',
|
||||
}
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
|
||||
if self._ciphers:
|
||||
ciphersuites = ':'.join(self._ciphers)
|
||||
ret += ["-ciphersuites {ciphersuites}".format(ciphersuites=ciphersuites)]
|
||||
|
||||
if self._sig_algs:
|
||||
signature_algorithms = set(self._sig_algs + self._cert_sig_algs)
|
||||
signature_algorithms = ':'.join(signature_algorithms)
|
||||
ret += ["-sigalgs {signature_algorithms}".format(
|
||||
signature_algorithms=signature_algorithms)]
|
||||
|
||||
if self._named_groups:
|
||||
named_groups = ':'.join(
|
||||
map(lambda named_group: self.NAMED_GROUP[named_group], self._named_groups))
|
||||
ret += ["-groups {named_groups}".format(named_groups=named_groups)]
|
||||
|
||||
ret += ['-msg -tls1_3']
|
||||
|
||||
return ret
|
||||
|
||||
def pre_checks(self):
|
||||
ret = ["requires_openssl_tls1_3"]
|
||||
|
||||
# ffdh groups require at least openssl 3.0
|
||||
ffdh_groups = ['ffdhe2048']
|
||||
|
||||
if any(x in ffdh_groups for x in self._named_groups):
|
||||
ret = ["requires_openssl_tls1_3_with_ffdh"]
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class OpenSSLServ(OpenSSLBase):
|
||||
"""
|
||||
Generate test commands for OpenSSL server.
|
||||
"""
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
ret += ['-num_tickets 0 -no_resume_ephemeral -no_cache']
|
||||
return ret
|
||||
|
||||
def post_checks(self):
|
||||
return ['-c "HTTP/1.0 200 ok"']
|
||||
|
||||
def pre_cmd(self):
|
||||
ret = ['$O_NEXT_SRV_NO_CERT']
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
|
||||
ret += ['-cert {cert} -key {key}'.format(cert=cert, key=key)]
|
||||
return ret
|
||||
|
||||
|
||||
class OpenSSLCli(OpenSSLBase):
|
||||
"""
|
||||
Generate test commands for OpenSSL client.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
return ['$O_NEXT_CLI_NO_CERT',
|
||||
'-CAfile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
|
||||
|
||||
|
||||
class GnuTLSBase(TLSProgram):
|
||||
"""
|
||||
Generate base test commands for GnuTLS.
|
||||
"""
|
||||
|
||||
CIPHER_SUITE = {
|
||||
'TLS_AES_256_GCM_SHA384': [
|
||||
'AES-256-GCM',
|
||||
'SHA384',
|
||||
'AEAD'],
|
||||
'TLS_AES_128_GCM_SHA256': [
|
||||
'AES-128-GCM',
|
||||
'SHA256',
|
||||
'AEAD'],
|
||||
'TLS_CHACHA20_POLY1305_SHA256': [
|
||||
'CHACHA20-POLY1305',
|
||||
'SHA256',
|
||||
'AEAD'],
|
||||
'TLS_AES_128_CCM_SHA256': [
|
||||
'AES-128-CCM',
|
||||
'SHA256',
|
||||
'AEAD'],
|
||||
'TLS_AES_128_CCM_8_SHA256': [
|
||||
'AES-128-CCM-8',
|
||||
'SHA256',
|
||||
'AEAD']}
|
||||
|
||||
SIGNATURE_ALGORITHM = {
|
||||
'ecdsa_secp256r1_sha256': ['SIGN-ECDSA-SECP256R1-SHA256'],
|
||||
'ecdsa_secp521r1_sha512': ['SIGN-ECDSA-SECP521R1-SHA512'],
|
||||
'ecdsa_secp384r1_sha384': ['SIGN-ECDSA-SECP384R1-SHA384'],
|
||||
'rsa_pss_rsae_sha256': ['SIGN-RSA-PSS-RSAE-SHA256']}
|
||||
|
||||
NAMED_GROUP = {
|
||||
'secp256r1': ['GROUP-SECP256R1'],
|
||||
'secp384r1': ['GROUP-SECP384R1'],
|
||||
'secp521r1': ['GROUP-SECP521R1'],
|
||||
'x25519': ['GROUP-X25519'],
|
||||
'x448': ['GROUP-X448'],
|
||||
'ffdhe2048': ['GROUP-FFDHE2048'],
|
||||
}
|
||||
|
||||
def pre_checks(self):
|
||||
return ["requires_gnutls_tls1_3",
|
||||
"requires_gnutls_next_no_ticket"]
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
|
||||
priority_string_list = []
|
||||
|
||||
def update_priority_string_list(items, map_table):
|
||||
for item in items:
|
||||
for i in map_table[item]:
|
||||
if i not in priority_string_list:
|
||||
yield i
|
||||
|
||||
if self._ciphers:
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
self._ciphers, self.CIPHER_SUITE))
|
||||
else:
|
||||
priority_string_list.extend(['CIPHER-ALL', 'MAC-ALL'])
|
||||
|
||||
if self._sig_algs:
|
||||
signature_algorithms = set(self._sig_algs + self._cert_sig_algs)
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
signature_algorithms, self.SIGNATURE_ALGORITHM))
|
||||
else:
|
||||
priority_string_list.append('SIGN-ALL')
|
||||
|
||||
|
||||
if self._named_groups:
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
self._named_groups, self.NAMED_GROUP))
|
||||
else:
|
||||
priority_string_list.append('GROUP-ALL')
|
||||
|
||||
priority_string_list = ['NONE'] + \
|
||||
priority_string_list + ['VERS-TLS1.3']
|
||||
|
||||
priority_string = ':+'.join(priority_string_list)
|
||||
priority_string += ':%NO_TICKETS'
|
||||
|
||||
ret += ['--priority={priority_string}'.format(
|
||||
priority_string=priority_string)]
|
||||
return ret
|
||||
|
||||
class GnuTLSServ(GnuTLSBase):
|
||||
"""
|
||||
Generate test commands for GnuTLS server.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
ret = ['$G_NEXT_SRV_NO_CERT', '--http', '--disable-client-cert', '--debug=4']
|
||||
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
|
||||
ret += ['--x509certfile {cert} --x509keyfile {key}'.format(
|
||||
cert=cert, key=key)]
|
||||
return ret
|
||||
|
||||
def post_checks(self):
|
||||
return ['-c "HTTP/1.0 200 OK"']
|
||||
|
||||
|
||||
class GnuTLSCli(GnuTLSBase):
|
||||
"""
|
||||
Generate test commands for GnuTLS client.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
return ['$G_NEXT_CLI_NO_CERT', '--debug=4', '--single-key-share',
|
||||
'--x509cafile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
|
||||
|
||||
|
||||
class MbedTLSBase(TLSProgram):
|
||||
"""
|
||||
Generate base test commands for mbedTLS.
|
||||
"""
|
||||
|
||||
CIPHER_SUITE = {
|
||||
'TLS_AES_256_GCM_SHA384': 'TLS1-3-AES-256-GCM-SHA384',
|
||||
'TLS_AES_128_GCM_SHA256': 'TLS1-3-AES-128-GCM-SHA256',
|
||||
'TLS_CHACHA20_POLY1305_SHA256': 'TLS1-3-CHACHA20-POLY1305-SHA256',
|
||||
'TLS_AES_128_CCM_SHA256': 'TLS1-3-AES-128-CCM-SHA256',
|
||||
'TLS_AES_128_CCM_8_SHA256': 'TLS1-3-AES-128-CCM-8-SHA256'}
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
ret += ['debug_level=4']
|
||||
|
||||
|
||||
if self._ciphers:
|
||||
ciphers = ','.join(
|
||||
map(lambda cipher: self.CIPHER_SUITE[cipher], self._ciphers))
|
||||
ret += ["force_ciphersuite={ciphers}".format(ciphers=ciphers)]
|
||||
|
||||
if self._sig_algs + self._cert_sig_algs:
|
||||
ret += ['sig_algs={sig_algs}'.format(
|
||||
sig_algs=','.join(set(self._sig_algs + self._cert_sig_algs)))]
|
||||
|
||||
if self._named_groups:
|
||||
named_groups = ','.join(self._named_groups)
|
||||
ret += ["groups={named_groups}".format(named_groups=named_groups)]
|
||||
return ret
|
||||
|
||||
#pylint: disable=missing-function-docstring
|
||||
def add_ffdh_group_requirements(self, requirement_list):
|
||||
if 'ffdhe2048' in self._named_groups:
|
||||
requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048')
|
||||
if 'ffdhe3072' in self._named_groups:
|
||||
requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048')
|
||||
if 'ffdhe4096' in self._named_groups:
|
||||
requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048')
|
||||
if 'ffdhe6144' in self._named_groups:
|
||||
requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048')
|
||||
if 'ffdhe8192' in self._named_groups:
|
||||
requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048')
|
||||
|
||||
def pre_checks(self):
|
||||
ret = ['requires_config_enabled MBEDTLS_DEBUG_C',
|
||||
'requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED']
|
||||
|
||||
if 'rsa_pss_rsae_sha256' in self._sig_algs + self._cert_sig_algs:
|
||||
ret.append(
|
||||
'requires_config_enabled MBEDTLS_X509_RSASSA_PSS_SUPPORT')
|
||||
|
||||
ec_groups = ['secp256r1', 'secp384r1', 'secp521r1', 'x25519', 'x448']
|
||||
ffdh_groups = ['ffdhe2048', 'ffdhe3072', 'ffdhe4096', 'ffdhe6144', 'ffdhe8192']
|
||||
|
||||
if any(x in ec_groups for x in self._named_groups):
|
||||
ret.append('requires_config_enabled PSA_WANT_ALG_ECDH')
|
||||
|
||||
if any(x in ffdh_groups for x in self._named_groups):
|
||||
ret.append('requires_config_enabled PSA_WANT_ALG_FFDH')
|
||||
self.add_ffdh_group_requirements(ret)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class MbedTLSServ(MbedTLSBase):
|
||||
"""
|
||||
Generate test commands for mbedTLS server.
|
||||
"""
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
ret += ['tls13_kex_modes=ephemeral cookies=0 tickets=0']
|
||||
return ret
|
||||
|
||||
def pre_checks(self):
|
||||
return ['requires_config_enabled MBEDTLS_SSL_SRV_C'] + super().pre_checks()
|
||||
|
||||
def post_checks(self):
|
||||
check_strings = ["Protocol is TLSv1.3"]
|
||||
if self._ciphers:
|
||||
check_strings.append(
|
||||
"server hello, chosen ciphersuite: {} ( id={:04d} )".format(
|
||||
self.CIPHER_SUITE[self._ciphers[0]],
|
||||
CIPHER_SUITE_IANA_VALUE[self._ciphers[0]]))
|
||||
if self._sig_algs:
|
||||
check_strings.append(
|
||||
"received signature algorithm: 0x{:x}".format(
|
||||
SIG_ALG_IANA_VALUE[self._sig_algs[0]]))
|
||||
|
||||
for named_group in self._named_groups:
|
||||
check_strings += ['got named group: {named_group}({iana_value:04x})'.format(
|
||||
named_group=named_group,
|
||||
iana_value=NAMED_GROUP_IANA_VALUE[named_group])]
|
||||
|
||||
check_strings.append("Certificate verification was skipped")
|
||||
return ['-s "{}"'.format(i) for i in check_strings]
|
||||
|
||||
def pre_cmd(self):
|
||||
ret = ['$P_SRV']
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
|
||||
ret += ['crt_file={cert} key_file={key}'.format(cert=cert, key=key)]
|
||||
return ret
|
||||
|
||||
def hrr_post_checks(self, named_group):
|
||||
return ['-s "HRR selected_group: {:s}"'.format(named_group)]
|
||||
|
||||
|
||||
class MbedTLSCli(MbedTLSBase):
|
||||
"""
|
||||
Generate test commands for mbedTLS client.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
return ['$P_CLI',
|
||||
'ca_file={cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
|
||||
|
||||
def pre_checks(self):
|
||||
return ['requires_config_enabled MBEDTLS_SSL_CLI_C'] + super().pre_checks()
|
||||
|
||||
def hrr_post_checks(self, named_group):
|
||||
ret = ['-c "received HelloRetryRequest message"']
|
||||
ret += ['-c "selected_group ( {:d} )"'.format(NAMED_GROUP_IANA_VALUE[named_group])]
|
||||
return ret
|
||||
|
||||
def post_checks(self):
|
||||
check_strings = ["Protocol is TLSv1.3"]
|
||||
if self._ciphers:
|
||||
check_strings.append(
|
||||
"server hello, chosen ciphersuite: ( {:04x} ) - {}".format(
|
||||
CIPHER_SUITE_IANA_VALUE[self._ciphers[0]],
|
||||
self.CIPHER_SUITE[self._ciphers[0]]))
|
||||
if self._sig_algs:
|
||||
check_strings.append(
|
||||
"Certificate Verify: Signature algorithm ( {:04x} )".format(
|
||||
SIG_ALG_IANA_VALUE[self._sig_algs[0]]))
|
||||
|
||||
for named_group in self._named_groups:
|
||||
check_strings += ['NamedGroup: {named_group} ( {iana_value:x} )'.format(
|
||||
named_group=named_group,
|
||||
iana_value=NAMED_GROUP_IANA_VALUE[named_group])]
|
||||
|
||||
check_strings.append("Verifying peer X.509 certificate... ok")
|
||||
return ['-c "{}"'.format(i) for i in check_strings]
|
||||
|
||||
|
||||
SERVER_CLASSES = {'OpenSSL': OpenSSLServ, 'GnuTLS': GnuTLSServ, 'mbedTLS': MbedTLSServ}
|
||||
CLIENT_CLASSES = {'OpenSSL': OpenSSLCli, 'GnuTLS': GnuTLSCli, 'mbedTLS': MbedTLSCli}
|
||||
|
||||
|
||||
def generate_compat_test(client=None, server=None, cipher=None, named_group=None, sig_alg=None):
|
||||
"""
|
||||
Generate test case with `ssl-opt.sh` format.
|
||||
"""
|
||||
name = 'TLS 1.3 {client[0]}->{server[0]}: {cipher},{named_group},{sig_alg}'.format(
|
||||
client=client, server=server, cipher=cipher[4:], sig_alg=sig_alg, named_group=named_group)
|
||||
|
||||
server_object = SERVER_CLASSES[server](ciphersuite=cipher,
|
||||
named_group=named_group,
|
||||
signature_algorithm=sig_alg,
|
||||
cert_sig_alg=sig_alg)
|
||||
client_object = CLIENT_CLASSES[client](ciphersuite=cipher,
|
||||
named_group=named_group,
|
||||
signature_algorithm=sig_alg,
|
||||
cert_sig_alg=sig_alg)
|
||||
|
||||
cmd = ['run_test "{}"'.format(name),
|
||||
'"{}"'.format(' '.join(server_object.cmd())),
|
||||
'"{}"'.format(' '.join(client_object.cmd())),
|
||||
'0']
|
||||
cmd += server_object.post_checks()
|
||||
cmd += client_object.post_checks()
|
||||
cmd += ['-C "received HelloRetryRequest message"']
|
||||
prefix = ' \\\n' + (' '*9)
|
||||
cmd = prefix.join(cmd)
|
||||
return '\n'.join(server_object.pre_checks() + client_object.pre_checks() + [cmd])
|
||||
|
||||
|
||||
def generate_hrr_compat_test(client=None, server=None,
|
||||
client_named_group=None, server_named_group=None,
|
||||
cert_sig_alg=None):
|
||||
"""
|
||||
Generate Hello Retry Request test case with `ssl-opt.sh` format.
|
||||
"""
|
||||
name = 'TLS 1.3 {client[0]}->{server[0]}: HRR {c_named_group} -> {s_named_group}'.format(
|
||||
client=client, server=server, c_named_group=client_named_group,
|
||||
s_named_group=server_named_group)
|
||||
server_object = SERVER_CLASSES[server](named_group=server_named_group,
|
||||
cert_sig_alg=cert_sig_alg)
|
||||
|
||||
client_object = CLIENT_CLASSES[client](named_group=client_named_group,
|
||||
cert_sig_alg=cert_sig_alg)
|
||||
client_object.add_named_groups(server_named_group)
|
||||
|
||||
cmd = ['run_test "{}"'.format(name),
|
||||
'"{}"'.format(' '.join(server_object.cmd())),
|
||||
'"{}"'.format(' '.join(client_object.cmd())),
|
||||
'0']
|
||||
cmd += server_object.post_checks()
|
||||
cmd += client_object.post_checks()
|
||||
cmd += server_object.hrr_post_checks(server_named_group)
|
||||
cmd += client_object.hrr_post_checks(server_named_group)
|
||||
prefix = ' \\\n' + (' '*9)
|
||||
cmd = prefix.join(cmd)
|
||||
return '\n'.join(server_object.pre_checks() +
|
||||
client_object.pre_checks() +
|
||||
[cmd])
|
||||
|
||||
SSL_OUTPUT_HEADER = '''\
|
||||
# TLS 1.3 interoperability test cases (equivalent of compat.sh for TLS 1.3).
|
||||
#
|
||||
# Automatically generated by {cmd}. Do not edit!
|
||||
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
'''
|
||||
DATA_FILES_PATH_VAR = '''
|
||||
DATA_FILES_PATH=../framework/data_files
|
||||
'''
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function of this program
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('-o', '--output',
|
||||
default='tests/opt-testcases/tls13-compat.sh',
|
||||
help='Output file path (not used with -1)')
|
||||
|
||||
parser.add_argument('-1', '--single', action='store_true',
|
||||
help='Print a single test case')
|
||||
# Single mode used to be the default.
|
||||
parser.add_argument('-a', '--generate-all-tls13-compat-tests',
|
||||
action='store_false', dest='single',
|
||||
help='Generate all test cases (negates -1) (default)')
|
||||
|
||||
parser.add_argument('--list-ciphers', action='store_true',
|
||||
default=False, help='List supported ciphersuites')
|
||||
|
||||
parser.add_argument('--list-sig-algs', action='store_true',
|
||||
default=False, help='List supported signature algorithms')
|
||||
|
||||
parser.add_argument('--list-named-groups', action='store_true',
|
||||
default=False, help='List supported named groups')
|
||||
|
||||
parser.add_argument('--list-servers', action='store_true',
|
||||
default=False, help='List supported TLS servers')
|
||||
|
||||
parser.add_argument('--list-clients', action='store_true',
|
||||
default=False, help='List supported TLS Clients')
|
||||
|
||||
parser.add_argument('server', choices=SERVER_CLASSES.keys(), nargs='?',
|
||||
default=list(SERVER_CLASSES.keys())[0],
|
||||
help='Choose TLS server program for test')
|
||||
parser.add_argument('client', choices=CLIENT_CLASSES.keys(), nargs='?',
|
||||
default=list(CLIENT_CLASSES.keys())[0],
|
||||
help='Choose TLS client program for test')
|
||||
parser.add_argument('cipher', choices=CIPHER_SUITE_IANA_VALUE.keys(), nargs='?',
|
||||
default=list(CIPHER_SUITE_IANA_VALUE.keys())[0],
|
||||
help='Choose cipher suite for test')
|
||||
parser.add_argument('sig_alg', choices=SIG_ALG_IANA_VALUE.keys(), nargs='?',
|
||||
default=list(SIG_ALG_IANA_VALUE.keys())[0],
|
||||
help='Choose cipher suite for test')
|
||||
parser.add_argument('named_group', choices=NAMED_GROUP_IANA_VALUE.keys(), nargs='?',
|
||||
default=list(NAMED_GROUP_IANA_VALUE.keys())[0],
|
||||
help='Choose cipher suite for test')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
def get_all_test_cases():
|
||||
# Generate normal compat test cases
|
||||
for client, server, cipher, named_group, sig_alg in \
|
||||
itertools.product(CLIENT_CLASSES.keys(),
|
||||
SERVER_CLASSES.keys(),
|
||||
CIPHER_SUITE_IANA_VALUE.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys(),
|
||||
SIG_ALG_IANA_VALUE.keys()):
|
||||
if server == 'mbedTLS' or client == 'mbedTLS':
|
||||
yield generate_compat_test(client=client, server=server,
|
||||
cipher=cipher, named_group=named_group,
|
||||
sig_alg=sig_alg)
|
||||
|
||||
|
||||
# Generate Hello Retry Request compat test cases
|
||||
for client, server, client_named_group, server_named_group in \
|
||||
itertools.product(CLIENT_CLASSES.keys(),
|
||||
SERVER_CLASSES.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys()):
|
||||
|
||||
if (client == 'mbedTLS' or server == 'mbedTLS') and \
|
||||
client_named_group != server_named_group:
|
||||
yield generate_hrr_compat_test(client=client, server=server,
|
||||
client_named_group=client_named_group,
|
||||
server_named_group=server_named_group,
|
||||
cert_sig_alg="ecdsa_secp256r1_sha256")
|
||||
|
||||
if not args.single:
|
||||
if args.output:
|
||||
with open(args.output, 'w', encoding="utf-8") as f:
|
||||
f.write(SSL_OUTPUT_HEADER.format(
|
||||
filename=os.path.basename(args.output),
|
||||
cmd=os.path.basename(sys.argv[0])))
|
||||
f.write(DATA_FILES_PATH_VAR)
|
||||
f.write('\n\n'.join(get_all_test_cases()))
|
||||
f.write('\n')
|
||||
else:
|
||||
print('\n\n'.join(get_all_test_cases()))
|
||||
return 0
|
||||
|
||||
if args.list_ciphers or args.list_sig_algs or args.list_named_groups \
|
||||
or args.list_servers or args.list_clients:
|
||||
if args.list_ciphers:
|
||||
print(*CIPHER_SUITE_IANA_VALUE.keys())
|
||||
if args.list_sig_algs:
|
||||
print(*SIG_ALG_IANA_VALUE.keys())
|
||||
if args.list_named_groups:
|
||||
print(*NAMED_GROUP_IANA_VALUE.keys())
|
||||
if args.list_servers:
|
||||
print(*SERVER_CLASSES.keys())
|
||||
if args.list_clients:
|
||||
print(*CLIENT_CLASSES.keys())
|
||||
return 0
|
||||
|
||||
print(generate_compat_test(server=args.server, client=args.client, sig_alg=args.sig_alg,
|
||||
cipher=args.cipher, named_group=args.named_group))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
@ -1,180 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# translate_ciphers.py
|
||||
#
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
Translate standard ciphersuite names to GnuTLS, OpenSSL and Mbed TLS standards.
|
||||
|
||||
To test the translation functions run:
|
||||
python3 -m unittest translate_cipher.py
|
||||
"""
|
||||
|
||||
import re
|
||||
import argparse
|
||||
import unittest
|
||||
|
||||
class TestTranslateCiphers(unittest.TestCase):
|
||||
"""
|
||||
Ensure translate_ciphers.py translates and formats ciphersuite names
|
||||
correctly
|
||||
"""
|
||||
def test_translate_all_cipher_names(self):
|
||||
"""
|
||||
Translate standard ciphersuite names to GnuTLS, OpenSSL and
|
||||
Mbed TLS counterpart. Use only a small subset of ciphers
|
||||
that exercise each step of the translation functions
|
||||
"""
|
||||
ciphers = [
|
||||
("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
|
||||
"+ECDHE-ECDSA:+NULL:+SHA1",
|
||||
"ECDHE-ECDSA-NULL-SHA",
|
||||
"TLS-ECDHE-ECDSA-WITH-NULL-SHA"),
|
||||
("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"+ECDHE-ECDSA:+AES-128-GCM:+AEAD",
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||
"TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"),
|
||||
("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"+DHE-RSA:+3DES-CBC:+SHA1",
|
||||
"EDH-RSA-DES-CBC3-SHA",
|
||||
"TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"),
|
||||
("TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"+RSA:+AES-256-CBC:+SHA1",
|
||||
"AES256-SHA",
|
||||
"TLS-RSA-WITH-AES-256-CBC-SHA"),
|
||||
("TLS_PSK_WITH_3DES_EDE_CBC_SHA",
|
||||
"+PSK:+3DES-CBC:+SHA1",
|
||||
"PSK-3DES-EDE-CBC-SHA",
|
||||
"TLS-PSK-WITH-3DES-EDE-CBC-SHA"),
|
||||
("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
None,
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305",
|
||||
"TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"),
|
||||
("TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
|
||||
"+ECDHE-ECDSA:+AES-128-CCM:+AEAD",
|
||||
None,
|
||||
"TLS-ECDHE-ECDSA-WITH-AES-128-CCM"),
|
||||
("TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384",
|
||||
None,
|
||||
"ECDHE-ARIA256-GCM-SHA384",
|
||||
"TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384"),
|
||||
]
|
||||
|
||||
for s, g_exp, o_exp, m_exp in ciphers:
|
||||
|
||||
if g_exp is not None:
|
||||
g = translate_gnutls(s)
|
||||
self.assertEqual(g, g_exp)
|
||||
|
||||
if o_exp is not None:
|
||||
o = translate_ossl(s)
|
||||
self.assertEqual(o, o_exp)
|
||||
|
||||
if m_exp is not None:
|
||||
m = translate_mbedtls(s)
|
||||
self.assertEqual(m, m_exp)
|
||||
|
||||
def translate_gnutls(s_cipher):
|
||||
"""
|
||||
Translate s_cipher from standard ciphersuite naming convention
|
||||
and return the GnuTLS naming convention
|
||||
"""
|
||||
|
||||
# Replace "_" with "-" to handle ciphersuite names based on Mbed TLS
|
||||
# naming convention
|
||||
s_cipher = s_cipher.replace("_", "-")
|
||||
|
||||
s_cipher = re.sub(r'\ATLS-', '+', s_cipher)
|
||||
s_cipher = s_cipher.replace("-WITH-", ":+")
|
||||
s_cipher = s_cipher.replace("-EDE", "")
|
||||
|
||||
# SHA in Mbed TLS == SHA1 GnuTLS,
|
||||
# if the last 3 chars are SHA append 1
|
||||
if s_cipher[-3:] == "SHA":
|
||||
s_cipher = s_cipher+"1"
|
||||
|
||||
# CCM or CCM-8 should be followed by ":+AEAD"
|
||||
# Replace "GCM:+SHAxyz" with "GCM:+AEAD"
|
||||
if "CCM" in s_cipher or "GCM" in s_cipher:
|
||||
s_cipher = re.sub(r"GCM-SHA\d\d\d", "GCM", s_cipher)
|
||||
s_cipher = s_cipher+":+AEAD"
|
||||
|
||||
# Replace the last "-" with ":+"
|
||||
else:
|
||||
index = s_cipher.rindex("-")
|
||||
s_cipher = s_cipher[:index] + ":+" + s_cipher[index+1:]
|
||||
|
||||
return s_cipher
|
||||
|
||||
def translate_ossl(s_cipher):
|
||||
"""
|
||||
Translate s_cipher from standard ciphersuite naming convention
|
||||
and return the OpenSSL naming convention
|
||||
"""
|
||||
|
||||
# Replace "_" with "-" to handle ciphersuite names based on Mbed TLS
|
||||
# naming convention
|
||||
s_cipher = s_cipher.replace("_", "-")
|
||||
|
||||
s_cipher = re.sub(r'^TLS-', '', s_cipher)
|
||||
s_cipher = s_cipher.replace("-WITH", "")
|
||||
|
||||
# Remove the "-" from "ABC-xyz"
|
||||
s_cipher = s_cipher.replace("AES-", "AES")
|
||||
s_cipher = s_cipher.replace("CAMELLIA-", "CAMELLIA")
|
||||
s_cipher = s_cipher.replace("ARIA-", "ARIA")
|
||||
|
||||
# Remove "RSA" if it is at the beginning
|
||||
s_cipher = re.sub(r'^RSA-', r'', s_cipher)
|
||||
|
||||
# For all circumstances outside of PSK
|
||||
if "PSK" not in s_cipher:
|
||||
s_cipher = s_cipher.replace("-EDE", "")
|
||||
s_cipher = s_cipher.replace("3DES-CBC", "DES-CBC3")
|
||||
|
||||
# Remove "CBC" if it is not prefixed by DES
|
||||
s_cipher = re.sub(r'(?<!DES-)CBC-', r'', s_cipher)
|
||||
|
||||
# ECDHE-RSA-ARIA does not exist in OpenSSL
|
||||
s_cipher = s_cipher.replace("ECDHE-RSA-ARIA", "ECDHE-ARIA")
|
||||
|
||||
# POLY1305 should not be followed by anything
|
||||
if "POLY1305" in s_cipher:
|
||||
index = s_cipher.rindex("POLY1305")
|
||||
s_cipher = s_cipher[:index+8]
|
||||
|
||||
# If DES is being used, Replace DHE with EDH
|
||||
if "DES" in s_cipher and "DHE" in s_cipher and "ECDHE" not in s_cipher:
|
||||
s_cipher = s_cipher.replace("DHE", "EDH")
|
||||
|
||||
return s_cipher
|
||||
|
||||
def translate_mbedtls(s_cipher):
|
||||
"""
|
||||
Translate s_cipher from standard ciphersuite naming convention
|
||||
and return Mbed TLS ciphersuite naming convention
|
||||
"""
|
||||
|
||||
# Replace "_" with "-"
|
||||
s_cipher = s_cipher.replace("_", "-")
|
||||
|
||||
return s_cipher
|
||||
|
||||
def format_ciphersuite_names(mode, names):
|
||||
t = {"g": translate_gnutls,
|
||||
"o": translate_ossl,
|
||||
"m": translate_mbedtls
|
||||
}[mode]
|
||||
return " ".join(c + '=' + t(c) for c in names)
|
||||
|
||||
def main(target, names):
|
||||
print(format_ciphersuite_names(target, names))
|
||||
|
||||
if __name__ == "__main__":
|
||||
PARSER = argparse.ArgumentParser()
|
||||
PARSER.add_argument('target', metavar='TARGET', choices=['o', 'g', 'm'])
|
||||
PARSER.add_argument('names', metavar='NAMES', nargs='+')
|
||||
ARGS = PARSER.parse_args()
|
||||
main(ARGS.target, ARGS.names)
|
@ -30,13 +30,16 @@ Public key write check EC 521 bits (DER)
|
||||
depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_SECP521R1
|
||||
pk_write_pubkey_check:"../framework/data_files/ec_521_pub.der":TEST_DER
|
||||
|
||||
Public key write check EC Brainpool 512 bits
|
||||
depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C:MBEDTLS_ECP_HAVE_BP512R1
|
||||
pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.pem":TEST_PEM
|
||||
## The pk_write_pubkey_check sometimes take ~3 hours to run with
|
||||
## GCC+Asan on the CI in the full config. Comment out the slowest
|
||||
## ones while we investigate and release 3.6.2.
|
||||
# Public key write check EC Brainpool 512 bits
|
||||
# depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C:MBEDTLS_ECP_HAVE_BP512R1
|
||||
# pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.pem":TEST_PEM
|
||||
|
||||
Public key write check EC Brainpool 512 bits (DER)
|
||||
depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_BP512R1
|
||||
pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.der":TEST_DER
|
||||
# Public key write check EC Brainpool 512 bits (DER)
|
||||
# depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_BP512R1
|
||||
# pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.der":TEST_DER
|
||||
|
||||
Public key write check EC X25519
|
||||
depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C:MBEDTLS_ECP_HAVE_CURVE25519
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "pk_internal.h"
|
||||
#include "mbedtls/pem.h"
|
||||
#include "mbedtls/oid.h"
|
||||
#include "mbedtls/base64.h"
|
||||
#include "psa/crypto_sizes.h"
|
||||
|
||||
typedef enum {
|
||||
@ -73,6 +74,7 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der)
|
||||
unsigned char *check_buf = NULL;
|
||||
unsigned char *start_buf;
|
||||
size_t buf_len, check_buf_len;
|
||||
int expected_result;
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
mbedtls_svc_key_id_t opaque_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
@ -109,6 +111,17 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der)
|
||||
|
||||
start_buf = buf;
|
||||
buf_len = check_buf_len;
|
||||
if (is_der) {
|
||||
expected_result = MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
|
||||
} else {
|
||||
expected_result = MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
|
||||
}
|
||||
/* Intentionally pass a wrong size for the provided output buffer and check
|
||||
* that the writing functions fails as expected. */
|
||||
for (size_t i = 1; i < buf_len; i++) {
|
||||
TEST_EQUAL(pk_write_any_key(&key, &start_buf, &i, is_public_key,
|
||||
is_der), expected_result);
|
||||
}
|
||||
TEST_EQUAL(pk_write_any_key(&key, &start_buf, &buf_len, is_public_key,
|
||||
is_der), 0);
|
||||
|
||||
@ -127,6 +140,12 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der)
|
||||
TEST_EQUAL(mbedtls_pk_setup_opaque(&key, opaque_id), 0);
|
||||
start_buf = buf;
|
||||
buf_len = check_buf_len;
|
||||
/* Intentionally pass a wrong size for the provided output buffer and check
|
||||
* that the writing functions fails as expected. */
|
||||
for (size_t i = 1; i < buf_len; i++) {
|
||||
TEST_EQUAL(pk_write_any_key(&key, &start_buf, &i, is_public_key,
|
||||
is_der), expected_result);
|
||||
}
|
||||
TEST_EQUAL(pk_write_any_key(&key, &start_buf, &buf_len, is_public_key,
|
||||
is_der), 0);
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
Check compile time library version
|
||||
check_compiletime_version:"3.6.1"
|
||||
check_compiletime_version:"3.6.2"
|
||||
|
||||
Check runtime library version
|
||||
check_runtime_version:"3.6.1"
|
||||
check_runtime_version:"3.6.2"
|
||||
|
||||
Check for MBEDTLS_VERSION_C
|
||||
check_feature:"MBEDTLS_VERSION_C":0
|
||||
|
Loading…
x
Reference in New Issue
Block a user