mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-03-28 08:37:25 +00:00
Merge pull request #6632 from yanesca/refactor_bignum_test_framework
Refactor bignum test framework
This commit is contained in:
commit
0fc88779ec
@ -15,7 +15,12 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from typing import Iterator, List, Tuple, TypeVar
|
from typing import Iterator, List, Tuple, TypeVar, Any
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
from . import test_case
|
||||||
|
from . import test_data_generation
|
||||||
|
from .bignum_data import INPUTS_DEFAULT, MODULI_DEFAULT
|
||||||
|
|
||||||
T = TypeVar('T') #pylint: disable=invalid-name
|
T = TypeVar('T') #pylint: disable=invalid-name
|
||||||
|
|
||||||
@ -63,8 +68,7 @@ def combination_pairs(values: List[T]) -> List[Tuple[T, T]]:
|
|||||||
"""Return all pair combinations from input values."""
|
"""Return all pair combinations from input values."""
|
||||||
return [(x, y) for x in values for y in values]
|
return [(x, y) for x in values for y in values]
|
||||||
|
|
||||||
|
class OperationCommon(test_data_generation.BaseTest):
|
||||||
class OperationCommon:
|
|
||||||
"""Common features for bignum binary operations.
|
"""Common features for bignum binary operations.
|
||||||
|
|
||||||
This adds functionality common in binary operation tests.
|
This adds functionality common in binary operation tests.
|
||||||
@ -78,22 +82,106 @@ class OperationCommon:
|
|||||||
unique_combinations_only: Boolean to select if test case combinations
|
unique_combinations_only: Boolean to select if test case combinations
|
||||||
must be unique. If True, only A,B or B,A would be included as a test
|
must be unique. If True, only A,B or B,A would be included as a test
|
||||||
case. If False, both A,B and B,A would be included.
|
case. If False, both A,B and B,A would be included.
|
||||||
|
input_style: Controls the way how test data is passed to the functions
|
||||||
|
in the generated test cases. "variable" passes them as they are
|
||||||
|
defined in the python source. "arch_split" pads the values with
|
||||||
|
zeroes depending on the architecture/limb size. If this is set,
|
||||||
|
test cases are generated for all architectures.
|
||||||
|
arity: the number of operands for the operation. Currently supported
|
||||||
|
values are 1 and 2.
|
||||||
"""
|
"""
|
||||||
symbol = ""
|
symbol = ""
|
||||||
input_values = [] # type: List[str]
|
input_values = INPUTS_DEFAULT # type: List[str]
|
||||||
input_cases = [] # type: List[Tuple[str, str]]
|
input_cases = [] # type: List[Any]
|
||||||
unique_combinations_only = True
|
unique_combinations_only = False
|
||||||
|
input_styles = ["variable", "fixed", "arch_split"] # type: List[str]
|
||||||
|
input_style = "variable" # type: str
|
||||||
|
limb_sizes = [32, 64] # type: List[int]
|
||||||
|
arities = [1, 2]
|
||||||
|
arity = 2
|
||||||
|
|
||||||
def __init__(self, val_a: str, val_b: str) -> None:
|
def __init__(self, val_a: str, val_b: str = "0", bits_in_limb: int = 32) -> None:
|
||||||
self.arg_a = val_a
|
self.val_a = val_a
|
||||||
self.arg_b = val_b
|
self.val_b = val_b
|
||||||
|
# Setting the int versions here as opposed to making them @properties
|
||||||
|
# provides earlier/more robust input validation.
|
||||||
self.int_a = hex_to_int(val_a)
|
self.int_a = hex_to_int(val_a)
|
||||||
self.int_b = hex_to_int(val_b)
|
self.int_b = hex_to_int(val_b)
|
||||||
|
if bits_in_limb not in self.limb_sizes:
|
||||||
|
raise ValueError("Invalid number of bits in limb!")
|
||||||
|
if self.input_style == "arch_split":
|
||||||
|
self.dependencies = ["MBEDTLS_HAVE_INT{:d}".format(bits_in_limb)]
|
||||||
|
self.bits_in_limb = bits_in_limb
|
||||||
|
|
||||||
|
@property
|
||||||
|
def boundary(self) -> int:
|
||||||
|
if self.arity == 1:
|
||||||
|
return self.int_a
|
||||||
|
elif self.arity == 2:
|
||||||
|
return max(self.int_a, self.int_b)
|
||||||
|
raise ValueError("Unsupported number of operands!")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def limb_boundary(self) -> int:
|
||||||
|
return bound_mpi(self.boundary, self.bits_in_limb)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def limbs(self) -> int:
|
||||||
|
return limbs_mpi(self.boundary, self.bits_in_limb)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hex_digits(self) -> int:
|
||||||
|
return 2 * (self.limbs * self.bits_in_limb // 8)
|
||||||
|
|
||||||
|
def format_arg(self, val) -> str:
|
||||||
|
if self.input_style not in self.input_styles:
|
||||||
|
raise ValueError("Unknown input style!")
|
||||||
|
if self.input_style == "variable":
|
||||||
|
return val
|
||||||
|
else:
|
||||||
|
return val.zfill(self.hex_digits)
|
||||||
|
|
||||||
|
def format_result(self, res) -> str:
|
||||||
|
res_str = '{:x}'.format(res)
|
||||||
|
return quote_str(self.format_arg(res_str))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arg_a(self) -> str:
|
||||||
|
return self.format_arg(self.val_a)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arg_b(self) -> str:
|
||||||
|
if self.arity == 1:
|
||||||
|
raise AttributeError("Operation is unary and doesn't have arg_b!")
|
||||||
|
return self.format_arg(self.val_b)
|
||||||
|
|
||||||
def arguments(self) -> List[str]:
|
def arguments(self) -> List[str]:
|
||||||
return [
|
args = [quote_str(self.arg_a)]
|
||||||
quote_str(self.arg_a), quote_str(self.arg_b)
|
if self.arity == 2:
|
||||||
] + self.result()
|
args.append(quote_str(self.arg_b))
|
||||||
|
return args + self.result()
|
||||||
|
|
||||||
|
def description(self) -> str:
|
||||||
|
"""Generate a description for the test case.
|
||||||
|
|
||||||
|
If not set, case_description uses the form A `symbol` B, where symbol
|
||||||
|
is used to represent the operation. Descriptions of each value are
|
||||||
|
generated to provide some context to the test case.
|
||||||
|
"""
|
||||||
|
if not self.case_description:
|
||||||
|
if self.arity == 1:
|
||||||
|
self.case_description = "{} {:x}".format(
|
||||||
|
self.symbol, self.int_a
|
||||||
|
)
|
||||||
|
elif self.arity == 2:
|
||||||
|
self.case_description = "{:x} {} {:x}".format(
|
||||||
|
self.int_a, self.symbol, self.int_b
|
||||||
|
)
|
||||||
|
return super().description()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_valid(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def result(self) -> List[str]:
|
def result(self) -> List[str]:
|
||||||
@ -111,15 +199,134 @@ class OperationCommon:
|
|||||||
Combinations are first generated from all input values, and then
|
Combinations are first generated from all input values, and then
|
||||||
specific cases provided.
|
specific cases provided.
|
||||||
"""
|
"""
|
||||||
if cls.unique_combinations_only:
|
if cls.arity == 1:
|
||||||
yield from combination_pairs(cls.input_values)
|
yield from ((a, "0") for a in cls.input_values)
|
||||||
|
elif cls.arity == 2:
|
||||||
|
if cls.unique_combinations_only:
|
||||||
|
yield from combination_pairs(cls.input_values)
|
||||||
|
else:
|
||||||
|
yield from (
|
||||||
|
(a, b)
|
||||||
|
for a in cls.input_values
|
||||||
|
for b in cls.input_values
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
yield from (
|
raise ValueError("Unsupported number of operands!")
|
||||||
(a, b)
|
|
||||||
for a in cls.input_values
|
@classmethod
|
||||||
for b in cls.input_values
|
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
||||||
)
|
if cls.input_style not in cls.input_styles:
|
||||||
yield from cls.input_cases
|
raise ValueError("Unknown input style!")
|
||||||
|
if cls.arity not in cls.arities:
|
||||||
|
raise ValueError("Unsupported number of operands!")
|
||||||
|
if cls.input_style == "arch_split":
|
||||||
|
test_objects = (cls(a, b, bits_in_limb=bil)
|
||||||
|
for a, b in cls.get_value_pairs()
|
||||||
|
for bil in cls.limb_sizes)
|
||||||
|
special_cases = (cls(*args, bits_in_limb=bil) # type: ignore
|
||||||
|
for args in cls.input_cases
|
||||||
|
for bil in cls.limb_sizes)
|
||||||
|
else:
|
||||||
|
test_objects = (cls(a, b)
|
||||||
|
for a, b in cls.get_value_pairs())
|
||||||
|
special_cases = (cls(*args) for args in cls.input_cases)
|
||||||
|
yield from (valid_test_object.create_test_case()
|
||||||
|
for valid_test_object in filter(
|
||||||
|
lambda test_object: test_object.is_valid,
|
||||||
|
chain(test_objects, special_cases)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ModOperationCommon(OperationCommon):
|
||||||
|
#pylint: disable=abstract-method
|
||||||
|
"""Target for bignum mod_raw test case generation."""
|
||||||
|
moduli = MODULI_DEFAULT # type: List[str]
|
||||||
|
|
||||||
|
def __init__(self, val_n: str, val_a: str, val_b: str = "0",
|
||||||
|
bits_in_limb: int = 64) -> None:
|
||||||
|
super().__init__(val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb)
|
||||||
|
self.val_n = val_n
|
||||||
|
# Setting the int versions here as opposed to making them @properties
|
||||||
|
# provides earlier/more robust input validation.
|
||||||
|
self.int_n = hex_to_int(val_n)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def boundary(self) -> int:
|
||||||
|
return self.int_n
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arg_n(self) -> str:
|
||||||
|
return self.format_arg(self.val_n)
|
||||||
|
|
||||||
|
def arguments(self) -> List[str]:
|
||||||
|
return [quote_str(self.arg_n)] + super().arguments()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def r(self) -> int: # pylint: disable=invalid-name
|
||||||
|
l = limbs_mpi(self.int_n, self.bits_in_limb)
|
||||||
|
return bound_mpi_limbs(l, self.bits_in_limb)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def r_inv(self) -> int:
|
||||||
|
return invmod(self.r, self.int_n)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def r2(self) -> int: # pylint: disable=invalid-name
|
||||||
|
return pow(self.r, 2)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_valid(self) -> bool:
|
||||||
|
if self.int_a >= self.int_n:
|
||||||
|
return False
|
||||||
|
if self.arity == 2 and self.int_b >= self.int_n:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def description(self) -> str:
|
||||||
|
"""Generate a description for the test case.
|
||||||
|
|
||||||
|
It uses the form A `symbol` B mod N, where symbol is used to represent
|
||||||
|
the operation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.case_description:
|
||||||
|
return super().description() + " mod {:x}".format(self.int_n)
|
||||||
|
return super().description()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def input_cases_args(cls) -> Iterator[Tuple[Any, Any, Any]]:
|
||||||
|
if cls.arity == 1:
|
||||||
|
yield from ((n, a, "0") for a, n in cls.input_cases)
|
||||||
|
elif cls.arity == 2:
|
||||||
|
yield from ((n, a, b) for a, b, n in cls.input_cases)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unsupported number of operands!")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
||||||
|
if cls.input_style not in cls.input_styles:
|
||||||
|
raise ValueError("Unknown input style!")
|
||||||
|
if cls.arity not in cls.arities:
|
||||||
|
raise ValueError("Unsupported number of operands!")
|
||||||
|
if cls.input_style == "arch_split":
|
||||||
|
test_objects = (cls(n, a, b, bits_in_limb=bil)
|
||||||
|
for n in cls.moduli
|
||||||
|
for a, b in cls.get_value_pairs()
|
||||||
|
for bil in cls.limb_sizes)
|
||||||
|
special_cases = (cls(*args, bits_in_limb=bil)
|
||||||
|
for args in cls.input_cases_args()
|
||||||
|
for bil in cls.limb_sizes)
|
||||||
|
else:
|
||||||
|
test_objects = (cls(n, a, b)
|
||||||
|
for n in cls.moduli
|
||||||
|
for a, b in cls.get_value_pairs())
|
||||||
|
special_cases = (cls(*args) for args in cls.input_cases_args())
|
||||||
|
yield from (valid_test_object.create_test_case()
|
||||||
|
for valid_test_object in filter(
|
||||||
|
lambda test_object: test_object.is_valid,
|
||||||
|
chain(test_objects, special_cases)
|
||||||
|
))
|
||||||
|
|
||||||
# BEGIN MERGE SLOT 1
|
# BEGIN MERGE SLOT 1
|
||||||
|
|
||||||
|
@ -16,20 +16,19 @@
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from abc import ABCMeta
|
|
||||||
from typing import Dict, Iterator, List, Tuple
|
from typing import Dict, Iterator, List, Tuple
|
||||||
|
|
||||||
from . import test_case
|
from . import test_case
|
||||||
from . import test_data_generation
|
from . import test_data_generation
|
||||||
from . import bignum_common
|
from . import bignum_common
|
||||||
|
|
||||||
class BignumCoreTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
|
class BignumCoreTarget(test_data_generation.BaseTarget):
|
||||||
#pylint: disable=abstract-method
|
#pylint: disable=abstract-method, too-few-public-methods
|
||||||
"""Target for bignum core test case generation."""
|
"""Target for bignum core test case generation."""
|
||||||
target_basename = 'test_suite_bignum_core.generated'
|
target_basename = 'test_suite_bignum_core.generated'
|
||||||
|
|
||||||
|
|
||||||
class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta):
|
class BignumCoreShiftR(BignumCoreTarget, test_data_generation.BaseTest):
|
||||||
"""Test cases for mbedtls_bignum_core_shift_r()."""
|
"""Test cases for mbedtls_bignum_core_shift_r()."""
|
||||||
count = 0
|
count = 0
|
||||||
test_function = "mpi_core_shift_r"
|
test_function = "mpi_core_shift_r"
|
||||||
@ -69,7 +68,7 @@ class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta):
|
|||||||
for count in counts:
|
for count in counts:
|
||||||
yield cls(input_hex, descr, count).create_test_case()
|
yield cls(input_hex, descr, count).create_test_case()
|
||||||
|
|
||||||
class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta):
|
class BignumCoreCTLookup(BignumCoreTarget, test_data_generation.BaseTest):
|
||||||
"""Test cases for mbedtls_mpi_core_ct_uint_table_lookup()."""
|
"""Test cases for mbedtls_mpi_core_ct_uint_table_lookup()."""
|
||||||
test_function = "mpi_core_ct_uint_table_lookup"
|
test_function = "mpi_core_ct_uint_table_lookup"
|
||||||
test_name = "Constant time MPI table lookup"
|
test_name = "Constant time MPI table lookup"
|
||||||
@ -107,104 +106,33 @@ class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta):
|
|||||||
yield (cls(bitsize, bitsize_description, window_size)
|
yield (cls(bitsize, bitsize_description, window_size)
|
||||||
.create_test_case())
|
.create_test_case())
|
||||||
|
|
||||||
class BignumCoreOperation(bignum_common.OperationCommon, BignumCoreTarget, metaclass=ABCMeta):
|
|
||||||
#pylint: disable=abstract-method
|
|
||||||
"""Common features for bignum core operations."""
|
|
||||||
input_values = [
|
|
||||||
"0", "1", "3", "f", "fe", "ff", "100", "ff00", "fffe", "ffff", "10000",
|
|
||||||
"fffffffe", "ffffffff", "100000000", "1f7f7f7f7f7f7f",
|
|
||||||
"8000000000000000", "fefefefefefefefe", "fffffffffffffffe",
|
|
||||||
"ffffffffffffffff", "10000000000000000", "1234567890abcdef0",
|
|
||||||
"fffffffffffffffffefefefefefefefe", "fffffffffffffffffffffffffffffffe",
|
|
||||||
"ffffffffffffffffffffffffffffffff", "100000000000000000000000000000000",
|
|
||||||
"1234567890abcdef01234567890abcdef0",
|
|
||||||
"fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefe",
|
|
||||||
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
|
|
||||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
||||||
"10000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0",
|
|
||||||
(
|
|
||||||
"4df72d07b4b71c8dacb6cffa954f8d88254b6277099308baf003fab73227f34029"
|
|
||||||
"643b5a263f66e0d3c3fa297ef71755efd53b8fb6cb812c6bbf7bcf179298bd9947"
|
|
||||||
"c4c8b14324140a2c0f5fad7958a69050a987a6096e9f055fb38edf0c5889eca4a0"
|
|
||||||
"cfa99b45fbdeee4c696b328ddceae4723945901ec025076b12b"
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
def description(self) -> str:
|
class BignumCoreAddAndAddIf(BignumCoreTarget, bignum_common.OperationCommon):
|
||||||
"""Generate a description for the test case.
|
|
||||||
|
|
||||||
If not set, case_description uses the form A `symbol` B, where symbol
|
|
||||||
is used to represent the operation. Descriptions of each value are
|
|
||||||
generated to provide some context to the test case.
|
|
||||||
"""
|
|
||||||
if not self.case_description:
|
|
||||||
self.case_description = "{:x} {} {:x}".format(
|
|
||||||
self.int_a, self.symbol, self.int_b
|
|
||||||
)
|
|
||||||
return super().description()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
|
||||||
for a_value, b_value in cls.get_value_pairs():
|
|
||||||
yield cls(a_value, b_value).create_test_case()
|
|
||||||
|
|
||||||
|
|
||||||
class BignumCoreOperationArchSplit(BignumCoreOperation):
|
|
||||||
#pylint: disable=abstract-method
|
|
||||||
"""Common features for bignum core operations where the result depends on
|
|
||||||
the limb size."""
|
|
||||||
|
|
||||||
def __init__(self, val_a: str, val_b: str, bits_in_limb: int) -> None:
|
|
||||||
super().__init__(val_a, val_b)
|
|
||||||
bound_val = max(self.int_a, self.int_b)
|
|
||||||
self.bits_in_limb = bits_in_limb
|
|
||||||
self.bound = bignum_common.bound_mpi(bound_val, self.bits_in_limb)
|
|
||||||
limbs = bignum_common.limbs_mpi(bound_val, self.bits_in_limb)
|
|
||||||
byte_len = limbs * self.bits_in_limb // 8
|
|
||||||
self.hex_digits = 2 * byte_len
|
|
||||||
if self.bits_in_limb == 32:
|
|
||||||
self.dependencies = ["MBEDTLS_HAVE_INT32"]
|
|
||||||
elif self.bits_in_limb == 64:
|
|
||||||
self.dependencies = ["MBEDTLS_HAVE_INT64"]
|
|
||||||
else:
|
|
||||||
raise ValueError("Invalid number of bits in limb!")
|
|
||||||
self.arg_a = self.arg_a.zfill(self.hex_digits)
|
|
||||||
self.arg_b = self.arg_b.zfill(self.hex_digits)
|
|
||||||
|
|
||||||
def pad_to_limbs(self, val) -> str:
|
|
||||||
return "{:x}".format(val).zfill(self.hex_digits)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
|
||||||
for a_value, b_value in cls.get_value_pairs():
|
|
||||||
yield cls(a_value, b_value, 32).create_test_case()
|
|
||||||
yield cls(a_value, b_value, 64).create_test_case()
|
|
||||||
|
|
||||||
class BignumCoreAddAndAddIf(BignumCoreOperationArchSplit):
|
|
||||||
"""Test cases for bignum core add and add-if."""
|
"""Test cases for bignum core add and add-if."""
|
||||||
count = 0
|
count = 0
|
||||||
symbol = "+"
|
symbol = "+"
|
||||||
test_function = "mpi_core_add_and_add_if"
|
test_function = "mpi_core_add_and_add_if"
|
||||||
test_name = "mpi_core_add_and_add_if"
|
test_name = "mpi_core_add_and_add_if"
|
||||||
|
input_style = "arch_split"
|
||||||
|
unique_combinations_only = True
|
||||||
|
|
||||||
def result(self) -> List[str]:
|
def result(self) -> List[str]:
|
||||||
result = self.int_a + self.int_b
|
result = self.int_a + self.int_b
|
||||||
|
|
||||||
carry, result = divmod(result, self.bound)
|
carry, result = divmod(result, self.limb_boundary)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
bignum_common.quote_str(self.pad_to_limbs(result)),
|
self.format_result(result),
|
||||||
str(carry)
|
str(carry)
|
||||||
]
|
]
|
||||||
|
|
||||||
class BignumCoreSub(BignumCoreOperation):
|
|
||||||
|
class BignumCoreSub(BignumCoreTarget, bignum_common.OperationCommon):
|
||||||
"""Test cases for bignum core sub."""
|
"""Test cases for bignum core sub."""
|
||||||
count = 0
|
count = 0
|
||||||
symbol = "-"
|
symbol = "-"
|
||||||
test_function = "mpi_core_sub"
|
test_function = "mpi_core_sub"
|
||||||
test_name = "mbedtls_mpi_core_sub"
|
test_name = "mbedtls_mpi_core_sub"
|
||||||
unique_combinations_only = False
|
|
||||||
|
|
||||||
def result(self) -> List[str]:
|
def result(self) -> List[str]:
|
||||||
if self.int_a >= self.int_b:
|
if self.int_a >= self.int_b:
|
||||||
@ -224,12 +152,11 @@ class BignumCoreSub(BignumCoreOperation):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class BignumCoreMLA(BignumCoreOperation):
|
class BignumCoreMLA(BignumCoreTarget, bignum_common.OperationCommon):
|
||||||
"""Test cases for fixed-size multiply accumulate."""
|
"""Test cases for fixed-size multiply accumulate."""
|
||||||
count = 0
|
count = 0
|
||||||
test_function = "mpi_core_mla"
|
test_function = "mpi_core_mla"
|
||||||
test_name = "mbedtls_mpi_core_mla"
|
test_name = "mbedtls_mpi_core_mla"
|
||||||
unique_combinations_only = False
|
|
||||||
|
|
||||||
input_values = [
|
input_values = [
|
||||||
"0", "1", "fffe", "ffffffff", "100000000", "20000000000000",
|
"0", "1", "fffe", "ffffffff", "100000000", "20000000000000",
|
||||||
@ -288,6 +215,16 @@ class BignumCoreMLA(BignumCoreOperation):
|
|||||||
"\"{:x}\"".format(carry_8)
|
"\"{:x}\"".format(carry_8)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_value_pairs(cls) -> Iterator[Tuple[str, str]]:
|
||||||
|
"""Generator to yield pairs of inputs.
|
||||||
|
|
||||||
|
Combinations are first generated from all input values, and then
|
||||||
|
specific cases provided.
|
||||||
|
"""
|
||||||
|
yield from super().get_value_pairs()
|
||||||
|
yield from cls.input_cases
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
||||||
"""Override for additional scalar input."""
|
"""Override for additional scalar input."""
|
||||||
@ -297,7 +234,7 @@ class BignumCoreMLA(BignumCoreOperation):
|
|||||||
yield cur_op.create_test_case()
|
yield cur_op.create_test_case()
|
||||||
|
|
||||||
|
|
||||||
class BignumCoreMontmul(BignumCoreTarget):
|
class BignumCoreMontmul(BignumCoreTarget, test_data_generation.BaseTest):
|
||||||
"""Test cases for Montgomery multiplication."""
|
"""Test cases for Montgomery multiplication."""
|
||||||
count = 0
|
count = 0
|
||||||
test_function = "mpi_core_montmul"
|
test_function = "mpi_core_montmul"
|
||||||
|
136
scripts/mbedtls_dev/bignum_data.py
Normal file
136
scripts/mbedtls_dev/bignum_data.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
"""Base values and datasets for bignum generated tests and helper functions that
|
||||||
|
produced them."""
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
# Functions calling these were used to produce test data and are here only for
|
||||||
|
# reproducability, they are not used by the test generation framework/classes
|
||||||
|
try:
|
||||||
|
from Cryptodome.Util.number import isPrime, getPrime #type: ignore #pylint: disable=import-error
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Generated by bignum_common.gen_safe_prime(192,1)
|
||||||
|
SAFE_PRIME_192_BIT_SEED_1 = "d1c127a667786703830500038ebaef20e5a3e2dc378fb75b"
|
||||||
|
|
||||||
|
# First number generated by random.getrandbits(192) - seed(2,2), not a prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO1 = "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"
|
||||||
|
|
||||||
|
# Second number generated by random.getrandbits(192) - seed(2,2), not a prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO2 = "cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd"
|
||||||
|
|
||||||
|
# Third number generated by random.getrandbits(192) - seed(2,2), not a prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO3 = "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"
|
||||||
|
|
||||||
|
# Fourth number generated by random.getrandbits(192) - seed(2,2), not a prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO4 = "ffed9235288bc781ae66267594c9c9500925e4749b575bd1"
|
||||||
|
|
||||||
|
# Ninth number generated by random.getrandbits(192) - seed(2,2), not a prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO9 = "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"
|
||||||
|
|
||||||
|
# Generated by bignum_common.gen_safe_prime(1024,3)
|
||||||
|
SAFE_PRIME_1024_BIT_SEED_3 = ("c93ba7ec74d96f411ba008bdb78e63ff11bb5df46a51e16b"
|
||||||
|
"2c9d156f8e4e18abf5e052cb01f47d0d1925a77f60991577"
|
||||||
|
"e128fb6f52f34a27950a594baadd3d8057abeb222cf3cca9"
|
||||||
|
"62db16abf79f2ada5bd29ab2f51244bf295eff9f6aaba130"
|
||||||
|
"2efc449b128be75eeaca04bc3c1a155d11d14e8be32a2c82"
|
||||||
|
"87b3996cf6ad5223")
|
||||||
|
|
||||||
|
# First number generated by random.getrandbits(1024) - seed(4,2), not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO1 = ("6905269ed6f0b09f165c8ce36e2f24b43000de01b2ed40ed"
|
||||||
|
"3addccb2c33be0ac79d679346d4ac7a5c3902b38963dc6e8"
|
||||||
|
"534f45738d048ec0f1099c6c3e1b258fd724452ccea71ff4"
|
||||||
|
"a14876aeaff1a098ca5996666ceab360512bd13110722311"
|
||||||
|
"710cf5327ac435a7a97c643656412a9b8a1abcd1a6916c74"
|
||||||
|
"da4f9fc3c6da5d7")
|
||||||
|
|
||||||
|
# Second number generated by random.getrandbits(1024) - seed(4,2), not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO2 = ("f1cfd99216df648647adec26793d0e453f5082492d83a823"
|
||||||
|
"3fb62d2c81862fc9634f806fabf4a07c566002249b191bf4"
|
||||||
|
"d8441b5616332aca5f552773e14b0190d93936e1daca3c06"
|
||||||
|
"f5ff0c03bb5d7385de08caa1a08179104a25e4664f5253a0"
|
||||||
|
"2a3187853184ff27459142deccea264542a00403ce80c4b0"
|
||||||
|
"a4042bb3d4341aad")
|
||||||
|
|
||||||
|
# Third number generated by random.getrandbits(1024) - seed(4,2), not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO3 = ("14c15c910b11ad28cc21ce88d0060cc54278c2614e1bcb38"
|
||||||
|
"3bb4a570294c4ea3738d243a6e58d5ca49c7b59b995253fd"
|
||||||
|
"6c79a3de69f85e3131f3b9238224b122c3e4a892d9196ada"
|
||||||
|
"4fcfa583e1df8af9b474c7e89286a1754abcb06ae8abb93f"
|
||||||
|
"01d89a024cdce7a6d7288ff68c320f89f1347e0cdd905ecf"
|
||||||
|
"d160c5d0ef412ed6")
|
||||||
|
|
||||||
|
# Fourth number generated by random.getrandbits(1024) - seed(4,2), not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO4 = ("32decd6b8efbc170a26a25c852175b7a96b98b5fbf37a2be"
|
||||||
|
"6f98bca35b17b9662f0733c846bbe9e870ef55b1a1f65507"
|
||||||
|
"a2909cb633e238b4e9dd38b869ace91311021c9e32111ac1"
|
||||||
|
"ac7cc4a4ff4dab102522d53857c49391b36cc9aa78a330a1"
|
||||||
|
"a5e333cb88dcf94384d4cd1f47ca7883ff5a52f1a05885ac"
|
||||||
|
"7671863c0bdbc23a")
|
||||||
|
|
||||||
|
# Fifth number generated by random.getrandbits(1024) - seed(4,2), not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO5 = ("53be4721f5b9e1f5acdac615bc20f6264922b9ccf469aef8"
|
||||||
|
"f6e7d078e55b85dd1525f363b281b8885b69dc230af5ac87"
|
||||||
|
"0692b534758240df4a7a03052d733dcdef40af2e54c0ce68"
|
||||||
|
"1f44ebd13cc75f3edcb285f89d8cf4d4950b16ffc3e1ac3b"
|
||||||
|
"4708d9893a973000b54a23020fc5b043d6e4a51519d9c9cc"
|
||||||
|
"52d32377e78131c1")
|
||||||
|
|
||||||
|
# Adding 192 bit and 1024 bit numbers because these are the shortest required
|
||||||
|
# for ECC and RSA respectively.
|
||||||
|
INPUTS_DEFAULT = [
|
||||||
|
"0", "1", # corner cases
|
||||||
|
"2", "3", # small primes
|
||||||
|
"4", # non-prime even
|
||||||
|
"38", # small random
|
||||||
|
SAFE_PRIME_192_BIT_SEED_1, # prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO1, # not a prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO2, # not a prime
|
||||||
|
SAFE_PRIME_1024_BIT_SEED_3, # prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO1, # not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO3, # not a prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO2, # largest (not a prime)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Only odd moduli are present as in the new bignum code only odd moduli are
|
||||||
|
# supported for now.
|
||||||
|
MODULI_DEFAULT = [
|
||||||
|
"53", # safe prime
|
||||||
|
"45", # non-prime
|
||||||
|
SAFE_PRIME_192_BIT_SEED_1, # safe prime
|
||||||
|
RANDOM_192_BIT_SEED_2_NO4, # not a prime
|
||||||
|
SAFE_PRIME_1024_BIT_SEED_3, # safe prime
|
||||||
|
RANDOM_1024_BIT_SEED_4_NO5, # not a prime
|
||||||
|
]
|
||||||
|
|
||||||
|
def __gen_safe_prime(bits, seed):
|
||||||
|
'''
|
||||||
|
Generate a safe prime.
|
||||||
|
|
||||||
|
This function is intended for generating constants offline and shouldn't be
|
||||||
|
used in test generation classes.
|
||||||
|
|
||||||
|
Requires pycryptodomex for getPrime and isPrime and python 3.9 or later for
|
||||||
|
randbytes.
|
||||||
|
'''
|
||||||
|
rng = random.Random()
|
||||||
|
# We want reproducability across python versions
|
||||||
|
rng.seed(seed, version=2)
|
||||||
|
while True:
|
||||||
|
prime = 2*getPrime(bits-1, rng.randbytes)+1 #pylint: disable=no-member
|
||||||
|
if isPrime(prime, 1e-30):
|
||||||
|
return prime
|
@ -14,12 +14,10 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from abc import ABCMeta
|
|
||||||
|
|
||||||
from . import test_data_generation
|
from . import test_data_generation
|
||||||
|
|
||||||
class BignumModTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
|
class BignumModTarget(test_data_generation.BaseTarget):
|
||||||
#pylint: disable=abstract-method
|
#pylint: disable=abstract-method, too-few-public-methods
|
||||||
"""Target for bignum mod test case generation."""
|
"""Target for bignum mod test case generation."""
|
||||||
target_basename = 'test_suite_bignum_mod.generated'
|
target_basename = 'test_suite_bignum_mod.generated'
|
||||||
|
|
||||||
|
@ -14,89 +14,16 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from abc import ABCMeta
|
from typing import Dict, List
|
||||||
from typing import Dict, Iterator, List
|
|
||||||
|
|
||||||
from . import test_case
|
|
||||||
from . import test_data_generation
|
from . import test_data_generation
|
||||||
from . import bignum_common
|
from . import bignum_common
|
||||||
|
|
||||||
class BignumModRawTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
|
class BignumModRawTarget(test_data_generation.BaseTarget):
|
||||||
#pylint: disable=abstract-method
|
#pylint: disable=abstract-method, too-few-public-methods
|
||||||
"""Target for bignum mod_raw test case generation."""
|
"""Target for bignum mod_raw test case generation."""
|
||||||
target_basename = 'test_suite_bignum_mod_raw.generated'
|
target_basename = 'test_suite_bignum_mod_raw.generated'
|
||||||
|
|
||||||
class BignumModRawOperation(bignum_common.OperationCommon, BignumModRawTarget, metaclass=ABCMeta):
|
|
||||||
#pylint: disable=abstract-method
|
|
||||||
"""Target for bignum mod_raw test case generation."""
|
|
||||||
|
|
||||||
def __init__(self, val_n: str, val_a: str, val_b: str = "0", bits_in_limb: int = 64) -> None:
|
|
||||||
super().__init__(val_a=val_a, val_b=val_b)
|
|
||||||
self.val_n = val_n
|
|
||||||
self.bits_in_limb = bits_in_limb
|
|
||||||
|
|
||||||
@property
|
|
||||||
def int_n(self) -> int:
|
|
||||||
return bignum_common.hex_to_int(self.val_n)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def boundary(self) -> int:
|
|
||||||
data_in = [self.int_a, self.int_b, self.int_n]
|
|
||||||
return max([n for n in data_in if n is not None])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def limbs(self) -> int:
|
|
||||||
return bignum_common.limbs_mpi(self.boundary, self.bits_in_limb)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def hex_digits(self) -> int:
|
|
||||||
return 2 * (self.limbs * self.bits_in_limb // 8)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def hex_n(self) -> str:
|
|
||||||
return "{:x}".format(self.int_n).zfill(self.hex_digits)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def hex_a(self) -> str:
|
|
||||||
return "{:x}".format(self.int_a).zfill(self.hex_digits)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def hex_b(self) -> str:
|
|
||||||
return "{:x}".format(self.int_b).zfill(self.hex_digits)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def r(self) -> int: # pylint: disable=invalid-name
|
|
||||||
l = bignum_common.limbs_mpi(self.int_n, self.bits_in_limb)
|
|
||||||
return bignum_common.bound_mpi_limbs(l, self.bits_in_limb)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def r_inv(self) -> int:
|
|
||||||
return bignum_common.invmod(self.r, self.int_n)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def r2(self) -> int: # pylint: disable=invalid-name
|
|
||||||
return pow(self.r, 2)
|
|
||||||
|
|
||||||
class BignumModRawOperationArchSplit(BignumModRawOperation):
|
|
||||||
#pylint: disable=abstract-method
|
|
||||||
"""Common features for bignum mod raw operations where the result depends on
|
|
||||||
the limb size."""
|
|
||||||
|
|
||||||
limb_sizes = [32, 64] # type: List[int]
|
|
||||||
|
|
||||||
def __init__(self, val_n: str, val_a: str, val_b: str = "0", bits_in_limb: int = 64) -> None:
|
|
||||||
super().__init__(val_n=val_n, val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb)
|
|
||||||
|
|
||||||
if bits_in_limb not in self.limb_sizes:
|
|
||||||
raise ValueError("Invalid number of bits in limb!")
|
|
||||||
|
|
||||||
self.dependencies = ["MBEDTLS_HAVE_INT{:d}".format(bits_in_limb)]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
|
||||||
for a_value, b_value in cls.get_value_pairs():
|
|
||||||
for bil in cls.limb_sizes:
|
|
||||||
yield cls(a_value, b_value, bits_in_limb=bil).create_test_case()
|
|
||||||
# BEGIN MERGE SLOT 1
|
# BEGIN MERGE SLOT 1
|
||||||
|
|
||||||
# END MERGE SLOT 1
|
# END MERGE SLOT 1
|
||||||
@ -122,126 +49,35 @@ class BignumModRawOperationArchSplit(BignumModRawOperation):
|
|||||||
# END MERGE SLOT 6
|
# END MERGE SLOT 6
|
||||||
|
|
||||||
# BEGIN MERGE SLOT 7
|
# BEGIN MERGE SLOT 7
|
||||||
class BignumModRawConvertToMont(BignumModRawOperationArchSplit):
|
|
||||||
""" Test cases for mpi_mod_raw_to_mont_rep(). """
|
|
||||||
|
|
||||||
|
class BignumModRawConvertToMont(bignum_common.ModOperationCommon,
|
||||||
|
BignumModRawTarget):
|
||||||
|
""" Test cases for mpi_mod_raw_to_mont_rep(). """
|
||||||
test_function = "mpi_mod_raw_to_mont_rep"
|
test_function = "mpi_mod_raw_to_mont_rep"
|
||||||
test_name = "Convert into Mont: "
|
test_name = "Convert into Mont: "
|
||||||
|
symbol = "R *"
|
||||||
test_data_moduli = ["b",
|
input_style = "arch_split"
|
||||||
"fd",
|
arity = 1
|
||||||
"eeff99aa37",
|
|
||||||
"eeff99aa11",
|
|
||||||
"800000000005",
|
|
||||||
"7fffffffffffffff",
|
|
||||||
"80fe000a10000001",
|
|
||||||
"25a55a46e5da99c71c7",
|
|
||||||
"1058ad82120c3a10196bb36229c1",
|
|
||||||
"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f"
|
|
||||||
"18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a"
|
|
||||||
"98df75154f8c914a282f8b",
|
|
||||||
"8335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63",
|
|
||||||
"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f"
|
|
||||||
"2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a6"
|
|
||||||
"4d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2"
|
|
||||||
"deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d"
|
|
||||||
"6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a0"
|
|
||||||
"7e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d389"
|
|
||||||
"8c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6"
|
|
||||||
"bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3a"
|
|
||||||
"d4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181d"
|
|
||||||
"b8896f33bb12e6ef73f12ec5c5ea7a8a337"
|
|
||||||
]
|
|
||||||
|
|
||||||
test_input_numbers = ["0",
|
|
||||||
"1",
|
|
||||||
"97",
|
|
||||||
"f5",
|
|
||||||
"6f5c3",
|
|
||||||
"745bfe50f7",
|
|
||||||
"ffa1f9924123",
|
|
||||||
"334a8b983c79bd",
|
|
||||||
"5b84f632b58f3461",
|
|
||||||
"19acd15bc38008e1",
|
|
||||||
"ffffffffffffffff",
|
|
||||||
"54ce6a6bb8247fa0427cfc75a6b0599",
|
|
||||||
"fecafe8eca052f154ce6a6bb8247fa019558bfeecce9bb9",
|
|
||||||
"a87d7a56fa4bfdc7da42ef798b9cf6843d4c54794698cb14d72"
|
|
||||||
"851dec9586a319f4bb6d5695acbd7c92e7a42a5ede6972adcbc"
|
|
||||||
"f68425265887f2d721f462b7f1b91531bac29fa648facb8e3c6"
|
|
||||||
"1bd5ae42d5a59ba1c89a95897bfe541a8ce1d633b98f379c481"
|
|
||||||
"6f25e21f6ac49286b261adb4b78274fe5f61c187581f213e84b"
|
|
||||||
"2a821e341ef956ecd5de89e6c1a35418cd74a549379d2d4594a"
|
|
||||||
"577543147f8e35b3514e62cf3e89d1156cdc91ab5f4c928fbd6"
|
|
||||||
"9148c35df5962fed381f4d8a62852a36823d5425f7487c13a12"
|
|
||||||
"523473fb823aa9d6ea5f42e794e15f2c1a8785cf6b7d51a4617"
|
|
||||||
"947fb3baf674f74a673cf1d38126983a19ed52c7439fab42c2185"
|
|
||||||
]
|
|
||||||
|
|
||||||
descr_tpl = '{} #{} N: \"{}\" A: \"{}\".'
|
|
||||||
|
|
||||||
def result(self) -> List[str]:
|
def result(self) -> List[str]:
|
||||||
return [self.hex_x]
|
result = (self.int_a * self.r) % self.int_n
|
||||||
|
return [self.format_result(result)]
|
||||||
|
|
||||||
def arguments(self) -> List[str]:
|
|
||||||
return [bignum_common.quote_str(n) for n in [self.hex_n,
|
|
||||||
self.hex_a,
|
|
||||||
self.hex_x]]
|
|
||||||
|
|
||||||
def description(self) -> str:
|
class BignumModRawConvertFromMont(bignum_common.ModOperationCommon,
|
||||||
return self.descr_tpl.format(self.test_name,
|
BignumModRawTarget):
|
||||||
self.count,
|
|
||||||
self.int_n,
|
|
||||||
self.int_a)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
|
||||||
for bil in [32, 64]:
|
|
||||||
for n in cls.test_data_moduli:
|
|
||||||
for i in cls.test_input_numbers:
|
|
||||||
# Skip invalid combinations where A.limbs > N.limbs
|
|
||||||
if bignum_common.hex_to_int(i) > bignum_common.hex_to_int(n):
|
|
||||||
continue
|
|
||||||
yield cls(n, i, bits_in_limb=bil).create_test_case()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def x(self) -> int: # pylint: disable=invalid-name
|
|
||||||
return (self.int_a * self.r) % self.int_n
|
|
||||||
|
|
||||||
@property
|
|
||||||
def hex_x(self) -> str:
|
|
||||||
return "{:x}".format(self.x).zfill(self.hex_digits)
|
|
||||||
|
|
||||||
class BignumModRawConvertFromMont(BignumModRawConvertToMont):
|
|
||||||
""" Test cases for mpi_mod_raw_from_mont_rep(). """
|
""" Test cases for mpi_mod_raw_from_mont_rep(). """
|
||||||
|
|
||||||
test_function = "mpi_mod_raw_from_mont_rep"
|
test_function = "mpi_mod_raw_from_mont_rep"
|
||||||
test_name = "Convert from Mont: "
|
test_name = "Convert from Mont: "
|
||||||
|
symbol = "1/R *"
|
||||||
|
input_style = "arch_split"
|
||||||
|
arity = 1
|
||||||
|
|
||||||
|
def result(self) -> List[str]:
|
||||||
|
result = (self.int_a * self.r_inv) % self.int_n
|
||||||
|
return [self.format_result(result)]
|
||||||
|
|
||||||
test_input_numbers = ["0",
|
|
||||||
"1",
|
|
||||||
"3ca",
|
|
||||||
"539ed428",
|
|
||||||
"7dfe5c6beb35a2d6",
|
|
||||||
"dca8de1c2adfc6d7aafb9b48e",
|
|
||||||
"a7d17b6c4be72f3d5c16bf9c1af6fc933",
|
|
||||||
"2fec97beec546f9553142ed52f147845463f579",
|
|
||||||
"378dc83b8bc5a7b62cba495af4919578dce6d4f175cadc4f",
|
|
||||||
"b6415f2a1a8e48a518345db11f56db3829c8f2c6415ab4a395a"
|
|
||||||
"b3ac2ea4cbef4af86eb18a84eb6ded4c6ecbfc4b59c2879a675"
|
|
||||||
"487f687adea9d197a84a5242a5cf6125ce19a6ad2e7341f1c57"
|
|
||||||
"d43ea4f4c852a51cb63dabcd1c9de2b827a3146a3d175b35bea"
|
|
||||||
"41ae75d2a286a3e9d43623152ac513dcdea1d72a7da846a8ab3"
|
|
||||||
"58d9be4926c79cfb287cf1cf25b689de3b912176be5dcaf4d4c"
|
|
||||||
"6e7cb839a4a3243a6c47c1e2c99d65c59d6fa3672575c2f1ca8"
|
|
||||||
"de6a32e854ec9d8ec635c96af7679fce26d7d159e4a9da3bd74"
|
|
||||||
"e1272c376cd926d74fe3fb164a5935cff3d5cdb92b35fe2cea32"
|
|
||||||
"138a7e6bfbc319ebd1725dacb9a359cbf693f2ecb785efb9d627"
|
|
||||||
]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def x(self): # pylint: disable=invalid-name
|
|
||||||
return (self.int_a * self.r_inv) % self.int_n
|
|
||||||
# END MERGE SLOT 7
|
# END MERGE SLOT 7
|
||||||
|
|
||||||
# BEGIN MERGE SLOT 8
|
# BEGIN MERGE SLOT 8
|
||||||
|
@ -25,6 +25,7 @@ import argparse
|
|||||||
import os
|
import os
|
||||||
import posixpath
|
import posixpath
|
||||||
import re
|
import re
|
||||||
|
import inspect
|
||||||
|
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
from typing import Callable, Dict, Iterable, Iterator, List, Type, TypeVar
|
from typing import Callable, Dict, Iterable, Iterator, List, Type, TypeVar
|
||||||
@ -35,12 +36,8 @@ from . import test_case
|
|||||||
T = TypeVar('T') #pylint: disable=invalid-name
|
T = TypeVar('T') #pylint: disable=invalid-name
|
||||||
|
|
||||||
|
|
||||||
class BaseTarget(metaclass=ABCMeta):
|
class BaseTest(metaclass=ABCMeta):
|
||||||
"""Base target for test case generation.
|
"""Base class for test case generation.
|
||||||
|
|
||||||
Child classes of this class represent an output file, and can be referred
|
|
||||||
to as file targets. These indicate where test cases will be written to for
|
|
||||||
all subclasses of the file target, which is set by `target_basename`.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
count: Counter for test cases from this class.
|
count: Counter for test cases from this class.
|
||||||
@ -48,8 +45,6 @@ class BaseTarget(metaclass=ABCMeta):
|
|||||||
automatically generated using the class, or manually set.
|
automatically generated using the class, or manually set.
|
||||||
dependencies: A list of dependencies required for the test case.
|
dependencies: A list of dependencies required for the test case.
|
||||||
show_test_count: Toggle for inclusion of `count` in the test description.
|
show_test_count: Toggle for inclusion of `count` in the test description.
|
||||||
target_basename: Basename of file to write generated tests to. This
|
|
||||||
should be specified in a child class of BaseTarget.
|
|
||||||
test_function: Test function which the class generates cases for.
|
test_function: Test function which the class generates cases for.
|
||||||
test_name: A common name or description of the test function. This can
|
test_name: A common name or description of the test function. This can
|
||||||
be `test_function`, a clearer equivalent, or a short summary of the
|
be `test_function`, a clearer equivalent, or a short summary of the
|
||||||
@ -59,7 +54,6 @@ class BaseTarget(metaclass=ABCMeta):
|
|||||||
case_description = ""
|
case_description = ""
|
||||||
dependencies = [] # type: List[str]
|
dependencies = [] # type: List[str]
|
||||||
show_test_count = True
|
show_test_count = True
|
||||||
target_basename = ""
|
|
||||||
test_function = ""
|
test_function = ""
|
||||||
test_name = ""
|
test_name = ""
|
||||||
|
|
||||||
@ -121,6 +115,21 @@ class BaseTarget(metaclass=ABCMeta):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTarget:
|
||||||
|
#pylint: disable=too-few-public-methods
|
||||||
|
"""Base target for test case generation.
|
||||||
|
|
||||||
|
Child classes of this class represent an output file, and can be referred
|
||||||
|
to as file targets. These indicate where test cases will be written to for
|
||||||
|
all subclasses of the file target, which is set by `target_basename`.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
target_basename: Basename of file to write generated tests to. This
|
||||||
|
should be specified in a child class of BaseTarget.
|
||||||
|
"""
|
||||||
|
target_basename = ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_tests(cls) -> Iterator[test_case.TestCase]:
|
def generate_tests(cls) -> Iterator[test_case.TestCase]:
|
||||||
"""Generate test cases for the class and its subclasses.
|
"""Generate test cases for the class and its subclasses.
|
||||||
@ -132,7 +141,8 @@ class BaseTarget(metaclass=ABCMeta):
|
|||||||
yield from `generate_tests()` in each. Calling this method on a class X
|
yield from `generate_tests()` in each. Calling this method on a class X
|
||||||
will yield test cases from all classes derived from X.
|
will yield test cases from all classes derived from X.
|
||||||
"""
|
"""
|
||||||
if cls.test_function:
|
if issubclass(cls, BaseTest) and not inspect.isabstract(cls):
|
||||||
|
#pylint: disable=no-member
|
||||||
yield from cls.generate_function_tests()
|
yield from cls.generate_function_tests()
|
||||||
for subclass in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
|
for subclass in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
|
||||||
yield from subclass.generate_tests()
|
yield from subclass.generate_tests()
|
||||||
|
@ -57,7 +57,7 @@ of BaseTarget in test_data_generation.py.
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from abc import ABCMeta
|
from abc import ABCMeta
|
||||||
from typing import Iterator, List
|
from typing import List
|
||||||
|
|
||||||
import scripts_path # pylint: disable=unused-import
|
import scripts_path # pylint: disable=unused-import
|
||||||
from mbedtls_dev import test_case
|
from mbedtls_dev import test_case
|
||||||
@ -68,15 +68,17 @@ from mbedtls_dev import bignum_common
|
|||||||
# the framework
|
# the framework
|
||||||
from mbedtls_dev import bignum_core, bignum_mod_raw # pylint: disable=unused-import
|
from mbedtls_dev import bignum_core, bignum_mod_raw # pylint: disable=unused-import
|
||||||
|
|
||||||
class BignumTarget(test_data_generation.BaseTarget, metaclass=ABCMeta):
|
class BignumTarget(test_data_generation.BaseTarget):
|
||||||
#pylint: disable=abstract-method
|
#pylint: disable=too-few-public-methods
|
||||||
"""Target for bignum (legacy) test case generation."""
|
"""Target for bignum (legacy) test case generation."""
|
||||||
target_basename = 'test_suite_bignum.generated'
|
target_basename = 'test_suite_bignum.generated'
|
||||||
|
|
||||||
|
|
||||||
class BignumOperation(bignum_common.OperationCommon, BignumTarget, metaclass=ABCMeta):
|
class BignumOperation(bignum_common.OperationCommon, BignumTarget,
|
||||||
|
metaclass=ABCMeta):
|
||||||
#pylint: disable=abstract-method
|
#pylint: disable=abstract-method
|
||||||
"""Common features for bignum operations in legacy tests."""
|
"""Common features for bignum operations in legacy tests."""
|
||||||
|
unique_combinations_only = True
|
||||||
input_values = [
|
input_values = [
|
||||||
"", "0", "-", "-0",
|
"", "0", "-", "-0",
|
||||||
"7b", "-7b",
|
"7b", "-7b",
|
||||||
@ -132,11 +134,6 @@ class BignumOperation(bignum_common.OperationCommon, BignumTarget, metaclass=ABC
|
|||||||
tmp = "large " + tmp
|
tmp = "large " + tmp
|
||||||
return tmp
|
return tmp
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
|
||||||
for a_value, b_value in cls.get_value_pairs():
|
|
||||||
yield cls(a_value, b_value).create_test_case()
|
|
||||||
|
|
||||||
|
|
||||||
class BignumCmp(BignumOperation):
|
class BignumCmp(BignumOperation):
|
||||||
"""Test cases for bignum value comparison."""
|
"""Test cases for bignum value comparison."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user