diff --git a/tests/include/test/arguments.h b/tests/include/test/arguments.h new file mode 100644 index 000000000..74bbbd569 --- /dev/null +++ b/tests/include/test/arguments.h @@ -0,0 +1,38 @@ +/** + * \file arguments.h + * + * \brief Manipulation of test arguments. + * + * Much of the code is in host_test.function, to be migrated here later. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_ARGUMENTS_H +#define TEST_ARGUMENTS_H + +#include "mbedtls/build_info.h" +#include +#include + +typedef union { + size_t len; + intmax_t sint; +} mbedtls_test_argument_t; + +#endif /* TEST_ARGUMENTS_H */ diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py index f19d30b61..839fccddd 100755 --- a/tests/scripts/generate_test_code.py +++ b/tests/scripts/generate_test_code.py @@ -171,6 +171,28 @@ import string import argparse +# Types recognized as signed integer arguments in test functions. +SIGNED_INTEGER_TYPES = frozenset([ + 'char', + 'short', + 'short int', + 'int', + 'int8_t', + 'int16_t', + 'int32_t', + 'int64_t', + 'intmax_t', + 'long', + 'long int', + 'long long int', + 'mbedtls_mpi_sint', + 'psa_status_t', +]) +# Types recognized as string arguments in test functions. +STRING_TYPES = frozenset(['char*', 'const char*', 'char const*']) +# Types recognized as hex data arguments in test functions. +DATA_TYPES = frozenset(['data_t*', 'const data_t*', 'data_t const*']) + BEGIN_HEADER_REGEX = r'/\*\s*BEGIN_HEADER\s*\*/' END_HEADER_REGEX = r'/\*\s*END_HEADER\s*\*/' @@ -192,9 +214,6 @@ CONDITION_REGEX = r'({})(?:\s*({})\s*({}))?$'.format(C_IDENTIFIER_REGEX, CONDITION_OPERATOR_REGEX, CONDITION_VALUE_REGEX) TEST_FUNCTION_VALIDATION_REGEX = r'\s*void\s+(?P\w+)\s*\(' -INT_CHECK_REGEX = r'int\s+.*' -CHAR_CHECK_REGEX = r'char\s*\*\s*.*' -DATA_T_CHECK_REGEX = r'data_t\s*\*\s*.*' FUNCTION_ARG_LIST_END_REGEX = r'.*\)' EXIT_LABEL_REGEX = r'^exit:' @@ -303,7 +322,7 @@ def gen_function_wrapper(name, local_vars, args_dispatch): :param name: Test function name :param local_vars: Local variables declaration code :param args_dispatch: List of dispatch arguments. - Ex: ['(char *)params[0]', '*((int *)params[1])'] + Ex: ['(char *) params[0]', '*((int *) params[1])'] :return: Test function wrapper. """ # Then create the wrapper @@ -444,6 +463,49 @@ def parse_function_dependencies(line): return dependencies +ARGUMENT_DECLARATION_REGEX = re.compile(r'(.+?) ?(?:\bconst\b)? ?(\w+)\Z', re.S) +def parse_function_argument(arg, arg_idx, args, local_vars, args_dispatch): + """ + Parses one test function's argument declaration. + + :param arg: argument declaration. + :param arg_idx: current wrapper argument index. + :param args: accumulator of arguments' internal types. + :param local_vars: accumulator of internal variable declarations. + :param args_dispatch: accumulator of argument usage expressions. + :return: the number of new wrapper arguments, + or None if the argument declaration is invalid. + """ + # Normalize whitespace + arg = arg.strip() + arg = re.sub(r'\s*\*\s*', r'*', arg) + arg = re.sub(r'\s+', r' ', arg) + # Extract name and type + m = ARGUMENT_DECLARATION_REGEX.search(arg) + if not m: + # E.g. "int x[42]" + return None + typ, _ = m.groups() + if typ in SIGNED_INTEGER_TYPES: + args.append('int') + args_dispatch.append('((mbedtls_test_argument_t *) params[%d])->sint' % arg_idx) + return 1 + if typ in STRING_TYPES: + args.append('char*') + args_dispatch.append('(char *) params[%d]' % arg_idx) + return 1 + if typ in DATA_TYPES: + args.append('hex') + # create a structure + pointer_initializer = '(uint8_t *) params[%d]' % arg_idx + len_initializer = '((mbedtls_test_argument_t *) params[%d])->len' % (arg_idx+1) + local_vars.append(' data_t data%d = {%s, %s};\n' % + (arg_idx, pointer_initializer, len_initializer)) + args_dispatch.append('&data%d' % arg_idx) + return 2 + return None + +ARGUMENT_LIST_REGEX = re.compile(r'\((.*?)\)', re.S) def parse_function_arguments(line): """ Parses test function signature for validation and generates @@ -455,42 +517,27 @@ def parse_function_arguments(line): :return: argument list, local variables for wrapper function and argument dispatch code. """ - args = [] - local_vars = '' - args_dispatch = [] - arg_idx = 0 - # Remove characters before arguments - line = line[line.find('(') + 1:] # Process arguments, ex: arg1, arg2 ) # This script assumes that the argument list is terminated by ')' # i.e. the test functions will not have a function pointer # argument. - for arg in line[:line.find(')')].split(','): - arg = arg.strip() - if arg == '': - continue - if re.search(INT_CHECK_REGEX, arg.strip()): - args.append('int') - args_dispatch.append('*( (int *) params[%d] )' % arg_idx) - elif re.search(CHAR_CHECK_REGEX, arg.strip()): - args.append('char*') - args_dispatch.append('(char *) params[%d]' % arg_idx) - elif re.search(DATA_T_CHECK_REGEX, arg.strip()): - args.append('hex') - # create a structure - pointer_initializer = '(uint8_t *) params[%d]' % arg_idx - len_initializer = '*( (uint32_t *) params[%d] )' % (arg_idx+1) - local_vars += """ data_t data%d = {%s, %s}; -""" % (arg_idx, pointer_initializer, len_initializer) - - args_dispatch.append('&data%d' % arg_idx) - arg_idx += 1 - else: + m = ARGUMENT_LIST_REGEX.search(line) + arg_list = m.group(1).strip() + if arg_list in ['', 'void']: + return [], '', [] + args = [] + local_vars = [] + args_dispatch = [] + arg_idx = 0 + for arg in arg_list.split(','): + indexes = parse_function_argument(arg, arg_idx, + args, local_vars, args_dispatch) + if indexes is None: raise ValueError("Test function arguments can only be 'int', " "'char *' or 'data_t'\n%s" % line) - arg_idx += 1 + arg_idx += indexes - return args, local_vars, args_dispatch + return args, ''.join(local_vars), args_dispatch def generate_function_code(name, code, local_vars, args_dispatch, @@ -705,7 +752,7 @@ def parse_test_data(data_f): execution. :param data_f: file object of the data file. - :return: Generator that yields test name, function name, + :return: Generator that yields line number, test name, function name, dependency list and function argument list. """ __state_read_name = 0 @@ -748,7 +795,7 @@ def parse_test_data(data_f): parts = escaped_split(line, ':') test_function = parts[0] args = parts[1:] - yield name, test_function, dependencies, args + yield data_f.line_no, name, test_function, dependencies, args dependencies = [] state = __state_read_name if state == __state_read_args: @@ -846,6 +893,14 @@ def write_dependencies(out_data_f, test_dependencies, unique_dependencies): return dep_check_code +INT_VAL_REGEX = re.compile(r'-?(\d+|0x[0-9a-f]+)$', re.I) +def val_is_int(val: str) -> bool: + """Whether val is suitable as an 'int' parameter in the .datax file.""" + if not INT_VAL_REGEX.match(val): + return False + # Limit the range to what is guaranteed to get through strtol() + return abs(int(val, 0)) <= 0x7fffffff + def write_parameters(out_data_f, test_args, func_args, unique_expressions): """ Writes test parameters to the intermediate data file, replacing @@ -864,9 +919,9 @@ def write_parameters(out_data_f, test_args, func_args, unique_expressions): typ = func_args[i] val = test_args[i] - # check if val is a non literal int val (i.e. an expression) - if typ == 'int' and not re.match(r'(\d+|0x[0-9a-f]+)$', - val, re.I): + # Pass small integer constants literally. This reduces the size of + # the C code. Register anything else as an expression. + if typ == 'int' and not val_is_int(val): typ = 'exp' if val not in unique_expressions: unique_expressions.append(val) @@ -909,6 +964,24 @@ def gen_suite_dep_checks(suite_dependencies, dep_check_code, expression_code): return dep_check_code, expression_code +def get_function_info(func_info, function_name, line_no): + """Look up information about a test function by name. + + Raise an informative expression if function_name is not found. + + :param func_info: dictionary mapping function names to their information. + :param function_name: the function name as written in the .function and + .data files. + :param line_no: line number for error messages. + :return Function information (id, args). + """ + test_function_name = 'test_' + function_name + if test_function_name not in func_info: + raise GeneratorInputError("%d: Function %s not found!" % + (line_no, test_function_name)) + return func_info[test_function_name] + + def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies): """ This function reads test case name, dependencies and test vectors @@ -931,7 +1004,7 @@ def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies): unique_expressions = [] dep_check_code = '' expression_code = '' - for test_name, function_name, test_dependencies, test_args in \ + for line_no, test_name, function_name, test_dependencies, test_args in \ parse_test_data(data_f): out_data_f.write(test_name + '\n') @@ -940,18 +1013,15 @@ def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies): unique_dependencies) # Write test function name - test_function_name = 'test_' + function_name - if test_function_name not in func_info: - raise GeneratorInputError("Function %s not found!" % - test_function_name) - func_id, func_args = func_info[test_function_name] + func_id, func_args = \ + get_function_info(func_info, function_name, line_no) out_data_f.write(str(func_id)) # Write parameters if len(test_args) != len(func_args): - raise GeneratorInputError("Invalid number of arguments in test " + raise GeneratorInputError("%d: Invalid number of arguments in test " "%s. See function %s signature." % - (test_name, function_name)) + (line_no, test_name, function_name)) expression_code += write_parameters(out_data_f, test_args, func_args, unique_expressions) diff --git a/tests/scripts/test_generate_test_code.py b/tests/scripts/test_generate_test_code.py index d23d74219..fe748aeb4 100755 --- a/tests/scripts/test_generate_test_code.py +++ b/tests/scripts/test_generate_test_code.py @@ -485,9 +485,10 @@ class ParseFuncSignature(TestCase): args, local, arg_dispatch = parse_function_arguments(line) self.assertEqual(args, ['char*', 'int', 'int']) self.assertEqual(local, '') - self.assertEqual(arg_dispatch, ['(char *) params[0]', - '*( (int *) params[1] )', - '*( (int *) params[2] )']) + self.assertEqual(arg_dispatch, + ['(char *) params[0]', + '((mbedtls_test_argument_t *) params[1])->sint', + '((mbedtls_test_argument_t *) params[2])->sint']) def test_hex_params(self): """ @@ -499,22 +500,22 @@ class ParseFuncSignature(TestCase): self.assertEqual(args, ['char*', 'hex', 'int']) self.assertEqual(local, ' data_t data1 = {(uint8_t *) params[1], ' - '*( (uint32_t *) params[2] )};\n') + '((mbedtls_test_argument_t *) params[2])->len};\n') self.assertEqual(arg_dispatch, ['(char *) params[0]', '&data1', - '*( (int *) params[3] )']) + '((mbedtls_test_argument_t *) params[3])->sint']) def test_unsupported_arg(self): """ - Test unsupported arguments (not among int, char * and data_t) + Test unsupported argument type :return: """ - line = 'void entropy_threshold( char * a, data_t * h, char result )' + line = 'void entropy_threshold( char * a, data_t * h, unknown_t result )' self.assertRaises(ValueError, parse_function_arguments, line) - def test_no_params(self): + def test_empty_params(self): """ - Test no parameters. + Test no parameters (nothing between parentheses). :return: """ line = 'void entropy_threshold()' @@ -523,6 +524,39 @@ class ParseFuncSignature(TestCase): self.assertEqual(local, '') self.assertEqual(arg_dispatch, []) + def test_blank_params(self): + """ + Test no parameters (space between parentheses). + :return: + """ + line = 'void entropy_threshold( )' + args, local, arg_dispatch = parse_function_arguments(line) + self.assertEqual(args, []) + self.assertEqual(local, '') + self.assertEqual(arg_dispatch, []) + + def test_void_params(self): + """ + Test no parameters (void keyword). + :return: + """ + line = 'void entropy_threshold(void)' + args, local, arg_dispatch = parse_function_arguments(line) + self.assertEqual(args, []) + self.assertEqual(local, '') + self.assertEqual(arg_dispatch, []) + + def test_void_space_params(self): + """ + Test no parameters (void with spaces). + :return: + """ + line = 'void entropy_threshold( void )' + args, local, arg_dispatch = parse_function_arguments(line) + self.assertEqual(args, []) + self.assertEqual(local, '') + self.assertEqual(arg_dispatch, []) + class ParseFunctionCode(TestCase): """ @@ -1264,29 +1298,33 @@ dhm_selftest: # List of (name, function_name, dependencies, args) tests = list(parse_test_data(stream)) test1, test2, test3, test4 = tests - self.assertEqual(test1[0], 'Diffie-Hellman full exchange #1') - self.assertEqual(test1[1], 'dhm_do_dhm') - self.assertEqual(test1[2], []) - self.assertEqual(test1[3], ['10', '"23"', '10', '"5"']) + self.assertEqual(test1[0], 3) + self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1') + self.assertEqual(test1[2], 'dhm_do_dhm') + self.assertEqual(test1[3], []) + self.assertEqual(test1[4], ['10', '"23"', '10', '"5"']) - self.assertEqual(test2[0], 'Diffie-Hellman full exchange #2') - self.assertEqual(test2[1], 'dhm_do_dhm') - self.assertEqual(test2[2], []) - self.assertEqual(test2[3], ['10', '"93450983094850938450983409623"', + self.assertEqual(test2[0], 6) + self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2') + self.assertEqual(test2[2], 'dhm_do_dhm') + self.assertEqual(test2[3], []) + self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"', '10', '"9345098304850938450983409622"']) - self.assertEqual(test3[0], 'Diffie-Hellman full exchange #3') - self.assertEqual(test3[1], 'dhm_do_dhm') - self.assertEqual(test3[2], []) - self.assertEqual(test3[3], ['10', + self.assertEqual(test3[0], 9) + self.assertEqual(test3[1], 'Diffie-Hellman full exchange #3') + self.assertEqual(test3[2], 'dhm_do_dhm') + self.assertEqual(test3[3], []) + self.assertEqual(test3[4], ['10', '"9345098382739712938719287391879381271"', '10', '"9345098792137312973297123912791271"']) - self.assertEqual(test4[0], 'Diffie-Hellman selftest') - self.assertEqual(test4[1], 'dhm_selftest') - self.assertEqual(test4[2], []) + self.assertEqual(test4[0], 12) + self.assertEqual(test4[1], 'Diffie-Hellman selftest') + self.assertEqual(test4[2], 'dhm_selftest') self.assertEqual(test4[3], []) + self.assertEqual(test4[4], []) def test_with_dependencies(self): """ @@ -1306,15 +1344,17 @@ dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622" # List of (name, function_name, dependencies, args) tests = list(parse_test_data(stream)) test1, test2 = tests - self.assertEqual(test1[0], 'Diffie-Hellman full exchange #1') - self.assertEqual(test1[1], 'dhm_do_dhm') - self.assertEqual(test1[2], ['YAHOO']) - self.assertEqual(test1[3], ['10', '"23"', '10', '"5"']) + self.assertEqual(test1[0], 4) + self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1') + self.assertEqual(test1[2], 'dhm_do_dhm') + self.assertEqual(test1[3], ['YAHOO']) + self.assertEqual(test1[4], ['10', '"23"', '10', '"5"']) - self.assertEqual(test2[0], 'Diffie-Hellman full exchange #2') - self.assertEqual(test2[1], 'dhm_do_dhm') - self.assertEqual(test2[2], []) - self.assertEqual(test2[3], ['10', '"93450983094850938450983409623"', + self.assertEqual(test2[0], 7) + self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2') + self.assertEqual(test2[2], 'dhm_do_dhm') + self.assertEqual(test2[3], []) + self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"', '10', '"9345098304850938450983409622"']) def test_no_args(self): @@ -1335,7 +1375,7 @@ dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622" stream = StringIOWrapper('test_suite_ut.function', data) err = None try: - for _, _, _, _ in parse_test_data(stream): + for _, _, _, _, _ in parse_test_data(stream): pass except GeneratorInputError as err: self.assertEqual(type(err), GeneratorInputError) @@ -1353,7 +1393,7 @@ depends_on:YAHOO stream = StringIOWrapper('test_suite_ut.function', data) err = None try: - for _, _, _, _ in parse_test_data(stream): + for _, _, _, _, _ in parse_test_data(stream): pass except GeneratorInputError as err: self.assertEqual(type(err), GeneratorInputError) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index 60eae9a64..86ff5b489 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -2,13 +2,18 @@ /*----------------------------------------------------------------------------*/ /* Headers */ +#include #include #include #include #include #include +#include +#include +#include #include +#include #if defined(MBEDTLS_ERROR_C) #include "mbedtls/error.h" @@ -19,23 +24,6 @@ #include "mbedtls/memory_buffer_alloc.h" #endif -#ifdef _MSC_VER -#include -typedef UINT8 uint8_t; -typedef INT32 int32_t; -typedef UINT32 uint32_t; -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include -#endif - -#include - -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__MINGW32__) -#include -#endif - #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include #endif diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function index 475a9c835..06f391fa4 100644 --- a/tests/suites/host_test.function +++ b/tests/suites/host_test.function @@ -28,50 +28,28 @@ int verify_string(char **str) * integer value. * * \param str Input string. - * \param value Pointer to int for output value. + * \param p_value Pointer to output value. * * \return 0 if success else 1 */ -int verify_int(char *str, int32_t *value) +int verify_int(char *str, intmax_t *p_value) { - size_t i; - int minus = 0; - int digits = 1; - int hex = 0; - - for (i = 0; i < strlen(str); i++) { - if (i == 0 && str[i] == '-') { - minus = 1; - continue; - } - - if (((minus && i == 2) || (!minus && i == 1)) && - str[i - 1] == '0' && (str[i] == 'x' || str[i] == 'X')) { - hex = 1; - continue; - } - - if (!((str[i] >= '0' && str[i] <= '9') || - (hex && ((str[i] >= 'a' && str[i] <= 'f') || - (str[i] >= 'A' && str[i] <= 'F'))))) { - digits = 0; - break; - } + char *end = NULL; + errno = 0; + /* Limit the range to long: for large integers, the test framework will + * use expressions anyway. */ + long value = strtol(str, &end, 0); + if (errno == EINVAL || *end != '\0') { + mbedtls_fprintf(stderr, + "Expected integer for parameter and got: %s\n", str); + return KEY_VALUE_MAPPING_NOT_FOUND; } - - if (digits) { - if (hex) { - *value = strtol(str, NULL, 16); - } else { - *value = strtol(str, NULL, 10); - } - - return 0; + if (errno == ERANGE) { + mbedtls_fprintf(stderr, "Integer out of range: %s\n", str); + return KEY_VALUE_MAPPING_NOT_FOUND; } - - mbedtls_fprintf(stderr, - "Expected integer for parameter and got: %s\n", str); - return KEY_VALUE_MAPPING_NOT_FOUND; + *p_value = value; + return 0; } @@ -180,24 +158,24 @@ static int parse_arguments(char *buf, size_t len, char **params, p++; } - /* Replace newlines, question marks and colons in strings */ + /* Replace backslash escapes in strings */ for (i = 0; i < cnt; i++) { p = params[i]; q = params[i]; while (*p != '\0') { - if (*p == '\\' && *(p + 1) == 'n') { - p += 2; - *(q++) = '\n'; - } else if (*p == '\\' && *(p + 1) == ':') { - p += 2; - *(q++) = ':'; - } else if (*p == '\\' && *(p + 1) == '?') { - p += 2; - *(q++) = '?'; - } else { - *(q++) = *(p++); + if (*p == '\\') { + ++p; + switch (*p) { + case 'n': + *p = '\n'; + break; + default: + // Fall through to copying *p + break; + } } + *(q++) = *(p++); } *q = '\0'; } @@ -223,7 +201,8 @@ static int parse_arguments(char *buf, size_t len, char **params, * * \return 0 for success else 1 */ -static int convert_params(size_t cnt, char **params, int32_t *int_params_store) +static int convert_params(size_t cnt, char **params, + mbedtls_test_argument_t *int_params_store) { char **cur = params; char **out = params; @@ -241,7 +220,7 @@ static int convert_params(size_t cnt, char **params, int32_t *int_params_store) break; } } else if (strcmp(type, "int") == 0) { - if (verify_int(val, int_params_store) == 0) { + if (verify_int(val, &int_params_store->sint) == 0) { *out++ = (char *) int_params_store++; } else { ret = (DISPATCH_INVALID_TEST_DATA); @@ -255,7 +234,7 @@ static int convert_params(size_t cnt, char **params, int32_t *int_params_store) mbedtls_test_unhexify((unsigned char *) val, strlen(val), val, &len) == 0); - *int_params_store = len; + int_params_store->len = len; *out++ = val; *out++ = (char *) (int_params_store++); } else { @@ -264,7 +243,7 @@ static int convert_params(size_t cnt, char **params, int32_t *int_params_store) } } else if (strcmp(type, "exp") == 0) { int exp_id = strtol(val, NULL, 10); - if (get_expression(exp_id, int_params_store) == 0) { + if (get_expression(exp_id, &int_params_store->sint) == 0) { *out++ = (char *) int_params_store++; } else { ret = (DISPATCH_INVALID_TEST_DATA); @@ -483,7 +462,7 @@ int execute_tests(int argc, const char **argv) char buf[5000]; char *params[50]; /* Store for processed integer params. */ - int32_t int_params[50]; + mbedtls_test_argument_t int_params[50]; void *pointer; #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) int stdout_fd = -1; diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function index 11a009afe..6c8d98e8b 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -69,7 +69,7 @@ __MBEDTLS_TEST_TEMPLATE__FUNCTIONS_CODE * * \return 0 if exp_id is found. 1 otherwise. */ -int get_expression(int32_t exp_id, int32_t *out_value) +int get_expression(int32_t exp_id, intmax_t *out_value) { int ret = KEY_VALUE_MAPPING_FOUND; diff --git a/tests/suites/test_suite_bignum.function b/tests/suites/test_suite_bignum.function index cefbfc37f..7f858e554 100644 --- a/tests/suites/test_suite_bignum.function +++ b/tests/suites/test_suite_bignum.function @@ -133,7 +133,7 @@ void mpi_read_write_string(int radix_X, char *input_X, int radix_A, TEST_ASSERT(sign_is_valid(&X)); TEST_ASSERT(mbedtls_mpi_write_string(&X, radix_A, str, output_size, &len) == result_write); if (result_write == 0) { - TEST_ASSERT(strcasecmp(str, input_A) == 0); + TEST_ASSERT(strcmp(str, input_A) == 0); TEST_ASSERT(str[len] == '!'); } } @@ -923,47 +923,16 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void mpi_mod_int(char *input_X, char *input_Y, - char *input_A, int mod_result) +void mpi_mod_int(char *input_X, mbedtls_mpi_sint y, + mbedtls_mpi_sint a, int mod_result) { mbedtls_mpi X; - mbedtls_mpi Y; - mbedtls_mpi A; int res; mbedtls_mpi_uint r; mbedtls_mpi_init(&X); - mbedtls_mpi_init(&Y); - mbedtls_mpi_init(&A); - /* We use MPIs to read Y and A since the test framework limits us to - * ints, so we can't have 64-bit values */ TEST_EQUAL(mbedtls_test_read_mpi(&X, input_X), 0); - TEST_EQUAL(mbedtls_test_read_mpi(&Y, input_Y), 0); - TEST_EQUAL(mbedtls_test_read_mpi(&A, input_A), 0); - - TEST_EQUAL(Y.n, 1); - TEST_EQUAL(A.n, 1); - - /* Convert the MPIs for Y and A to (signed) mbedtls_mpi_sints */ - - /* Since we're converting sign+magnitude to two's complement, we lose one - * bit of value in the output. This means there are some values we can't - * represent, e.g. (hex) -A0000000 on 32-bit systems. These are technically - * invalid test cases, so could be considered "won't happen", but they are - * easy to test for, and this helps guard against human error. */ - - mbedtls_mpi_sint y = (mbedtls_mpi_sint) Y.p[0]; - TEST_ASSERT(y >= 0); /* If y < 0 here, we can't make negative y */ - if (Y.s == -1) { - y = -y; - } - - mbedtls_mpi_sint a = (mbedtls_mpi_sint) A.p[0]; - TEST_ASSERT(a >= 0); /* Same goes for a */ - if (A.s == -1) { - a = -a; - } res = mbedtls_mpi_mod_int(&r, &X, y); TEST_EQUAL(res, mod_result); @@ -973,8 +942,6 @@ void mpi_mod_int(char *input_X, char *input_Y, exit: mbedtls_mpi_free(&X); - mbedtls_mpi_free(&Y); - mbedtls_mpi_free(&A); } /* END_CASE */ diff --git a/tests/suites/test_suite_bignum.misc.data b/tests/suites/test_suite_bignum.misc.data index 5eda4c11a..9d068f146 100644 --- a/tests/suites/test_suite_bignum.misc.data +++ b/tests/suites/test_suite_bignum.misc.data @@ -56,10 +56,10 @@ Test mpi_read_write_string #5 (Illegal output radix) mpi_read_write_string:16:"-23":17:"-23":4:0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA Test mpi_read_write_string #6 (Output radix of 15) -mpi_read_write_string:10:"29":15:"1e":100:0:0 +mpi_read_write_string:10:"29":15:"1E":100:0:0 Test mpi_read_write_string #7 -mpi_read_write_string:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":16:"0941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":200:0:0 +mpi_read_write_string:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":16:"0941379D00FED1491FE15DF284DFDE4A142F68AA8D412023195CEE66883E6290FFE703F4EA5963BF212713CEE46B107C09182B5EDCD955ADAC418BF4918E2889AF48E1099D513830CEC85C26AC1E158B52620E33BA8692F893EFBB2F958B4424":200:0:0 Test mpi_read_write_string #8 (Empty MPI hex -> hex) mpi_read_write_string:16:"":16:"":4:0:0 @@ -1229,45 +1229,45 @@ Test mbedtls_mpi_mod_mpi: -0 (null) % -42 mpi_mod_mpi:"-":"-2a":"":MBEDTLS_ERR_MPI_NEGATIVE_VALUE Base test mbedtls_mpi_mod_int #1 -mpi_mod_int:"3e8":"d":"c":0 +mpi_mod_int:"3e8":0xd:0xc:0 Base test mbedtls_mpi_mod_int #2 (Divide by zero) -mpi_mod_int:"3e8":"0":"0":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +mpi_mod_int:"3e8":0x0:0x0:MBEDTLS_ERR_MPI_DIVISION_BY_ZERO Base test mbedtls_mpi_mod_int #3 -mpi_mod_int:"-3e8":"d":"1":0 +mpi_mod_int:"-3e8":0xd:0x1:0 Base test mbedtls_mpi_mod_int #4 (Negative modulo) -mpi_mod_int:"3e8":"-d":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE +mpi_mod_int:"3e8":-0xd:0x0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE Base test mbedtls_mpi_mod_int #5 (Negative modulo) -mpi_mod_int:"-3e8":"-d":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE +mpi_mod_int:"-3e8":-0xd:0x0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE Base test mbedtls_mpi_mod_int #6 (By 1) -mpi_mod_int:"3e8":"1":"0":0 +mpi_mod_int:"3e8":0x1:0x0:0 Base test mbedtls_mpi_mod_int #7 (By 2) -mpi_mod_int:"3e9":"2":"1":0 +mpi_mod_int:"3e9":0x2:0x1:0 Base test mbedtls_mpi_mod_int #8 (By 2) -mpi_mod_int:"3e8":"2":"0":0 +mpi_mod_int:"3e8":0x2:0x0:0 Test mbedtls_mpi_mod_int: 0 (null) % 1 -mpi_mod_int:"":"1":"0":0 +mpi_mod_int:"":0x1:0x0:0 Test mbedtls_mpi_mod_int: 0 (null) % 2 -mpi_mod_int:"":"2":"0":0 +mpi_mod_int:"":0x2:0x0:0 Test mbedtls_mpi_mod_int: 0 (null) % -1 -mpi_mod_int:"":"-1":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE +mpi_mod_int:"":-0x1:0x0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE Test mbedtls_mpi_mod_int: 0 (null) % -2 -mpi_mod_int:"":"-2":"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE +mpi_mod_int:"":-0x2:0x0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE # CURRENTLY FAILS - SEE GITHUB ISSUE #6540 #Test mbedtls_mpi_mod_int: 230772460340063000000100500000300000010 % 5178236083361335880 -> 3386266129388798810 #depends_on:MBEDTLS_HAVE_INT64 -#mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA4847DCCA48":"2EFE6F1A7D28035A":0 +#mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980CEE30A":0x47DCCA4847DCCA48:0x2EFE6F1A7D28035A:0 Test mbedtls_mpi_mod_mpi: 230772460340063000000100500000300000010 % 5178236083361335880 -> 3386266129388798810 mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA4847DCCA48":"2EFE6F1A7D28035A":0 @@ -1275,7 +1275,7 @@ mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA4847DCCA48":"2EFE6F1A7D280 # CURRENTLY FAILS - SEE GITHUB ISSUE #6540 #Test mbedtls_mpi_mod_int: 230772460340062999996714233870911201200 % 5178236083361335880 -> 0 #depends_on:MBEDTLS_HAVE_INT64 -#mpi_mod_int:"AD9D28BF6C4E98FDC2584FEF03A6DFB0":"47DCCA4847DCCA48":"0":0 +#mpi_mod_int:"AD9D28BF6C4E98FDC2584FEF03A6DFB0":0x47DCCA4847DCCA48:0x0:0 Test mbedtls_mpi_mod_mpi: 230772460340062999996714233870911201200 % 5178236083361335880 -> 0 mpi_mod_mpi:"AD9D28BF6C4E98FDC2584FEF03A6DFB0":"47DCCA4847DCCA48":"0":0 @@ -1283,7 +1283,7 @@ mpi_mod_mpi:"AD9D28BF6C4E98FDC2584FEF03A6DFB0":"47DCCA4847DCCA48":"0":0 # CURRENTLY FAILS WHEN MPIS ARE 32-BIT (ISSUE #6450): WHEN FIXED, REMOVE "depends_on" LINE Test mbedtls_mpi_mod_int: 230772460340063000000100500000300000010 % 1205652040 -> 3644370 depends_on:MBEDTLS_HAVE_INT64 -mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA48":"379BD2":0 +mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980CEE30A":0x47DCCA48:0x379BD2:0 Test mbedtls_mpi_mod_mpi: 230772460340063000000100500000300000010 % 1205652040 -> 3644370 mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA48":"379BD2":0 @@ -1291,7 +1291,7 @@ mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980CEE30A":"47DCCA48":"379BD2":0 # CURRENTLY FAILS WHEN MPIS ARE 32-BIT (ISSUE #6450): WHEN FIXED, REMOVE "depends_on" LINE Test mbedtls_mpi_mod_int: 230772460340063000000100500000296355640 % 1205652040 -> 0 depends_on:MBEDTLS_HAVE_INT64 -mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980974738":"47DCCA48":"0":0 +mpi_mod_int:"AD9D28BF6C4E98FDF156BF0980974738":0x47DCCA48:0x0:0 Test mbedtls_mpi_mod_mpi: 230772460340063000000100500000296355640 % 1205652040 -> 0 mpi_mod_mpi:"AD9D28BF6C4E98FDF156BF0980974738":"47DCCA48":"0":0 diff --git a/tests/suites/test_suite_platform_printf.data b/tests/suites/test_suite_platform_printf.data new file mode 100644 index 000000000..891771b91 --- /dev/null +++ b/tests/suites/test_suite_platform_printf.data @@ -0,0 +1,114 @@ +# The test cases for printf and integers have two purposes: they exercise +# the printf function family, and they exercise the passing of integers +# and strings through the test framework. + +printf "%d", 0 +printf_int:"%d":0:"0" + +printf "%d", -0 +printf_int:"%d":-0:"0" + +printf "%d", 0x0 +printf_int:"%d":0x0:"0" + +printf "%d", 0x00 +printf_int:"%d":0x00:"0" + +printf "%d", 0x000000000000000000000000000000000000000000 +printf_int:"%d":0x000000000000000000000000000000000000000000:"0" + +printf "%d", -0x0 +printf_int:"%d":-0x0:"0" + +printf "%d", 1 +printf_int:"%d":1:"1" + +printf "%d", 0x1 +printf_int:"%d":0x1:"1" + +printf "%d", 0x0000000000000000000000000000000000000000001 +printf_int:"%d":0x0000000000000000000000000000000000000000001:"1" + +printf "%d", -1 +printf_int:"%d":-1:"-1" + +printf "%d", -0x1 +printf_int:"%d":-0x1:"-1" + +printf "%d", -0x0000000000000000000000000000000000000000001 +printf_int:"%d":-0x0000000000000000000000000000000000000000001:"-1" + +printf "%d", 2147483647 +printf_int:"%d":2147483647:"2147483647" + +printf "%d", 0x7fffffff +printf_int:"%d":0x7fffffff:"2147483647" + +printf "%d", -2147483647 +printf_int:"%d":-2147483647:"-2147483647" + +printf "%d", -0x7fffffff +printf_int:"%d":-0x7fffffff:"-2147483647" + +printf "%d", -2147483648 +printf_int:"%d":-2147483648:"-2147483648" + +printf "%d", -0x80000000 +printf_int:"%d":-0x80000000:"-2147483648" + +# Test that LONG_MAX is coming out untruncated through the test framework. +printf "%lx", LONG_MAX +printf_long_max:"%lx":LONG_MAX + +# The next few test cases exercise how the test framework handles special +# characters in strings. +printf "%c%c", SPACE, SPACE +printf_char2:"%c%c":SPACE_CHAR:SPACE_CHAR:" " + +printf "%c%c", NEWLINE, SPACE +printf_char2:"%c%c":NEWLINE_CHAR:SPACE_CHAR:"\n " + +printf "%c%c", DOUBLE QUOTE, SPACE +printf_char2:"%c%c":DOUBLE_QUOTE_CHAR:SPACE_CHAR:"\" " + +printf "%c%c", COLON, SPACE +printf_char2:"%c%c":COLON_CHAR:SPACE_CHAR:"\: " + +printf "%c%c", QUESTION, SPACE +printf_char2:"%c%c":QUESTION_CHAR:SPACE_CHAR:"? " + +printf "%c%c", BACKSLASH, SPACE +printf_char2:"%c%c":BACKSLASH_CHAR:SPACE_CHAR:"\\ " + +printf "%c%c", SPACE, BACKSLASH +printf_char2:"%c%c":SPACE_CHAR:BACKSLASH_CHAR:" \\" + +printf "%c%c", COLON, COLON +printf_char2:"%c%c":COLON_CHAR:COLON_CHAR:"\:\:" + +printf "%c%c", COLON, NEWLINE +printf_char2:"%c%c":COLON_CHAR:NEWLINE_CHAR:"\:\n" + +printf "%c%c", QUESTION, QUESTION +printf_char2:"%c%c":QUESTION_CHAR:QUESTION_CHAR:"??" + +printf "%c%c", QUESTION, NEWLINE +printf_char2:"%c%c":QUESTION_CHAR:NEWLINE_CHAR:"?\n" + +printf "%c%c", BACKSLASH, NEWLINE +printf_char2:"%c%c":BACKSLASH_CHAR:NEWLINE_CHAR:"\\\n" + +printf "%c%c", BACKSLASH, DOUBLE QUOTE +printf_char2:"%c%c":BACKSLASH_CHAR:DOUBLE_QUOTE_CHAR:"\\\"" + +printf "%c%c", BACKSLASH, COLON +printf_char2:"%c%c":BACKSLASH_CHAR:COLON_CHAR:"\\\:" + +printf "%c%c", BACKSLASH, QUESTION +printf_char2:"%c%c":BACKSLASH_CHAR:QUESTION_CHAR:"\\?" + +printf "%c%c", BACKSLASH, BACKSLASH +printf_char2:"%c%c":BACKSLASH_CHAR:BACKSLASH_CHAR:"\\\\" + +printf "%c%c", BACKSLASH, n +printf_char2:"%c%c":BACKSLASH_CHAR:LOWERCASE_N_CHAR:"\\n" diff --git a/tests/suites/test_suite_platform_printf.function b/tests/suites/test_suite_platform_printf.function new file mode 100644 index 000000000..3c816fe33 --- /dev/null +++ b/tests/suites/test_suite_platform_printf.function @@ -0,0 +1,89 @@ +/* BEGIN_HEADER */ + +/* The printf test functions take a format argument from the test data + * for several reasons: + * - For some tests, it makes sense to vary the format. + * - For all tests, it means we're testing the actual printf function + * that parses the format at runtime, and not a compiler optimization. + * (It may be useful to add tests that allow compiler optimizations. + * There aren't any yet at the time of writing.) + */ + +#include "mbedtls/platform.h" + +#include +#include +#include + +#define NEWLINE_CHAR '\n' +#define SPACE_CHAR ' ' +#define DOUBLE_QUOTE_CHAR '"' +#define COLON_CHAR ':' +#define QUESTION_CHAR '?' +#define BACKSLASH_CHAR '\\' +#define LOWERCASE_N_CHAR 'n' +/* END_HEADER */ + +/* BEGIN_CASE */ +void printf_int(char *format, /* any format expecting one int argument, e.g. "%d" */ + int x, char *result) +{ + char *output = NULL; + const size_t n = strlen(result); + + /* Nominal case: buffer just large enough */ + ASSERT_ALLOC(output, n + 1); + TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, x)); + ASSERT_COMPARE(result, n + 1, output, n + 1); + mbedtls_free(output); + output = NULL; + +exit: + mbedtls_free(output); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void printf_long_max(const char *format, /* "%lx" or longer type */ + long value) +{ + char *expected = NULL; + char *output = NULL; + /* 2 hex digits per byte */ + const size_t n = sizeof(value) * 2; + + /* We assume that long has no padding bits! */ + ASSERT_ALLOC(expected, n + 1); + expected[0] = '7'; + memset(expected + 1, 'f', sizeof(value) * 2 - 1); + + ASSERT_ALLOC(output, n + 1); + TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, value)); + ASSERT_COMPARE(expected, n + 1, output, n + 1); + mbedtls_free(output); + output = NULL; + +exit: + mbedtls_free(output); + mbedtls_free(expected); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void printf_char2(char *format, /* "%c%c" */ + int arg1, int arg2, char *result) +{ + char *output = NULL; + const size_t n = strlen(result); + + /* Nominal case: buffer just large enough */ + ASSERT_ALLOC(output, n + 1); + TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, arg1, arg2)); + ASSERT_COMPARE(result, n + 1, output, n + 1); + mbedtls_free(output); + output = NULL; + +exit: + mbedtls_free(output); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index fc8e6eb40..98b1a334b 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -2422,12 +2422,12 @@ exit: /* BEGIN_CASE */ void copy_success(int source_usage_arg, int source_alg_arg, int source_alg2_arg, - unsigned int source_lifetime_arg, + int source_lifetime_arg, int type_arg, data_t *material, int copy_attributes, int target_usage_arg, int target_alg_arg, int target_alg2_arg, - unsigned int target_lifetime_arg, + int target_lifetime_arg, int expected_usage_arg, int expected_alg_arg, int expected_alg2_arg) { diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index a6b001fb1..db2fe56a5 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -336,7 +336,7 @@ mbedtls_x509_csr_info:"data_files/server1.req.sha512":"CSR version \: 1\nsubje X509 CSR Information RSA with SHA-256, containing commas depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTS_X509_INFO -mbedtls_x509_csr_info:"data_files/server1.req.commas.sha256":"CSR version \: 1\nsubject name \: C=NL, O=PolarSSL\, Commas, CN=PolarSSL Server 1\nsigned using \: RSA with SHA-256\nRSA key size \: 2048 bits\n" +mbedtls_x509_csr_info:"data_files/server1.req.commas.sha256":"CSR version \: 1\nsubject name \: C=NL, O=PolarSSL\\, Commas, CN=PolarSSL Server 1\nsigned using \: RSA with SHA-256\nRSA key size \: 2048 bits\n" X509 CSR Information EC with SHA1 depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_MD_CAN_SHA1:!MBEDTLS_X509_REMOVE_INFO @@ -437,7 +437,7 @@ mbedtls_x509_dn_gets:"data_files/server2.crt":"issuer":"C=NL, O=PolarSSL, CN=Pol X509 Get Distinguished Name #5 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_CAN_SHA1 -mbedtls_x509_dn_gets:"data_files/server1.commas.crt":"subject":"C=NL, O=PolarSSL\, Commas, CN=PolarSSL Server 1" +mbedtls_x509_dn_gets:"data_files/server1.commas.crt":"subject":"C=NL, O=PolarSSL\\, Commas, CN=PolarSSL Server 1" X509 Get Modified DN #1 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_CAN_SHA1 @@ -3145,7 +3145,7 @@ x509_get_time:MBEDTLS_ASN1_UTC_TIME:"0002291212+0300":MBEDTLS_ERR_X509_INVALID_D X509 Get time (UTC invalid character in year) depends_on:MBEDTLS_X509_USE_C -x509_get_time:MBEDTLS_ASN1_UTC_TIME:"0\1130231212Z":MBEDTLS_ERR_X509_INVALID_DATE:0:0:0:0:0:0 +x509_get_time:MBEDTLS_ASN1_UTC_TIME:"0\\1130231212Z":MBEDTLS_ERR_X509_INVALID_DATE:0:0:0:0:0:0 X509 Get time (UTC invalid character in month) depends_on:MBEDTLS_X509_USE_C diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index bb40029bb..cd1b0a3bd 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -163,7 +163,7 @@ depends_on:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECDSA_DETERMI x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"":2:0:"data_files/test-ca2.crt" X509 String to Names #1 -mbedtls_x509_string_to_names:"C=NL,O=Offspark\, Inc., OU=PolarSSL":"C=NL, O=Offspark\, Inc., OU=PolarSSL":0 +mbedtls_x509_string_to_names:"C=NL,O=Offspark\\, Inc., OU=PolarSSL":"C=NL, O=Offspark\\, Inc., OU=PolarSSL":0 X509 String to Names #2 mbedtls_x509_string_to_names:"C=NL, O=Offspark, Inc., OU=PolarSSL":"":MBEDTLS_ERR_X509_UNKNOWN_OID @@ -175,10 +175,10 @@ X509 String to Names #4 (Name larger than 255 bytes) mbedtls_x509_string_to_names:"C=NL, O=1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456, OU=PolarSSL":"":MBEDTLS_ERR_X509_INVALID_NAME X509 String to Names #5 (Escape non-allowed characters) -mbedtls_x509_string_to_names:"C=NL, O=Offspark\a Inc., OU=PolarSSL":"":MBEDTLS_ERR_X509_INVALID_NAME +mbedtls_x509_string_to_names:"C=NL, O=Offspark\\a Inc., OU=PolarSSL":"":MBEDTLS_ERR_X509_INVALID_NAME X509 String to Names #6 (Escape at end) -mbedtls_x509_string_to_names:"C=NL, O=Offspark\":"":MBEDTLS_ERR_X509_INVALID_NAME +mbedtls_x509_string_to_names:"C=NL, O=Offspark\\":"":MBEDTLS_ERR_X509_INVALID_NAME Check max serial length x509_set_serial_check: