Merge pull request #6716 from gilles-peskine-arm/test-argument-types-union

Support larger integer test arguments
This commit is contained in:
Gilles Peskine 2023-05-04 10:05:20 +02:00 committed by GitHub
commit 2eff33cb6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 500 additions and 215 deletions

View File

@ -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 <stdint.h>
#include <stdlib.h>
typedef union {
size_t len;
intmax_t sint;
} mbedtls_test_argument_t;
#endif /* TEST_ARGUMENTS_H */

View File

@ -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<func_name>\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: <type> arg1, <type> 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)

View File

@ -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)

View File

@ -2,13 +2,18 @@
/*----------------------------------------------------------------------------*/
/* Headers */
#include <test/arguments.h>
#include <test/helpers.h>
#include <test/macros.h>
#include <test/random.h>
#include <test/bignum_helpers.h>
#include <test/psa_crypto_helpers.h>
#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#if defined(MBEDTLS_ERROR_C)
#include "mbedtls/error.h"
@ -19,23 +24,6 @@
#include "mbedtls/memory_buffer_alloc.h"
#endif
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT8 uint8_t;
typedef INT32 int32_t;
typedef UINT32 uint32_t;
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include <stdint.h>
#endif
#include <string.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__MINGW32__)
#include <strings.h>
#endif
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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"

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 */

View File

@ -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)
{

View File

@ -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

View File

@ -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: