File: bignum_mod_raw.py

package info (click to toggle)
mbedtls 3.6.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 50,424 kB
  • sloc: ansic: 164,526; sh: 25,295; python: 14,825; makefile: 2,761; perl: 1,043; tcl: 4
file content (242 lines) | stat: -rw-r--r-- 9,231 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
"""Framework classes for generation of bignum mod_raw test cases."""
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
#

from typing import Iterator, List

from . import test_case
from . import test_data_generation
from . import bignum_common
from .bignum_data import ONLY_PRIME_MODULI

class BignumModRawTarget(test_data_generation.BaseTarget):
    #pylint: disable=abstract-method, too-few-public-methods
    """Target for bignum mod_raw test case generation."""
    target_basename = 'test_suite_bignum_mod_raw.generated'


class BignumModRawSub(bignum_common.ModOperationCommon,
                      BignumModRawTarget):
    """Test cases for bignum mpi_mod_raw_sub()."""
    symbol = "-"
    test_function = "mpi_mod_raw_sub"
    test_name = "mbedtls_mpi_mod_raw_sub"
    input_style = "fixed"
    arity = 2

    def arguments(self) -> List[str]:
        return [bignum_common.quote_str(n) for n in [self.arg_a,
                                                     self.arg_b,
                                                     self.arg_n]
               ] + self.result()

    def result(self) -> List[str]:
        result = (self.int_a - self.int_b) % self.int_n
        return [self.format_result(result)]

class BignumModRawFixQuasiReduction(bignum_common.ModOperationCommon,
                                    BignumModRawTarget):
    """Test cases for ecp quasi_reduction()."""
    symbol = "-"
    test_function = "mpi_mod_raw_fix_quasi_reduction"
    test_name = "fix_quasi_reduction"
    input_style = "fixed"
    arity = 1

    # Extend the default values with n < x < 2n
    input_values = bignum_common.ModOperationCommon.input_values + [
        "73",

        # First number generated by random.getrandbits(1024) - seed(3,2)
        "ea7b5bf55eb561a4216363698b529b4a97b750923ceb3ffd",

        # First number generated by random.getrandbits(1024) - seed(1,2)
        ("cd447e35b8b6d8fe442e3d437204e52db2221a58008a05a6c4647159c324c985" +
         "9b810e766ec9d28663ca828dd5f4b3b2e4b06ce60741c7a87ce42c8218072e8c" +
         "35bf992dc9e9c616612e7696a6cecc1b78e510617311d8a3c2ce6f447ed4d57b" +
         "1e2feb89414c343c1027c4d1c386bbc4cd613e30d8f16adf91b7584a2265b1f5")
    ] # type: List[str]

    def result(self) -> List[str]:
        result = self.int_a % self.int_n
        return [self.format_result(result)]

    @property
    def is_valid(self) -> bool:
        return bool(self.int_a < 2 * self.int_n)

class BignumModRawMul(bignum_common.ModOperationCommon,
                      BignumModRawTarget):
    """Test cases for bignum mpi_mod_raw_mul()."""
    symbol = "*"
    test_function = "mpi_mod_raw_mul"
    test_name = "mbedtls_mpi_mod_raw_mul"
    input_style = "arch_split"
    arity = 2

    def arguments(self) -> List[str]:
        return [self.format_result(self.to_montgomery(self.int_a)),
                self.format_result(self.to_montgomery(self.int_b)),
                bignum_common.quote_str(self.arg_n)
               ] + self.result()

    def result(self) -> List[str]:
        result = (self.int_a * self.int_b) % self.int_n
        return [self.format_result(self.to_montgomery(result))]


class BignumModRawInvPrime(bignum_common.ModOperationCommon,
                           BignumModRawTarget):
    """Test cases for bignum mpi_mod_raw_inv_prime()."""
    moduli = ONLY_PRIME_MODULI
    symbol = "^ -1"
    test_function = "mpi_mod_raw_inv_prime"
    test_name = "mbedtls_mpi_mod_raw_inv_prime (Montgomery form only)"
    input_style = "arch_split"
    arity = 1
    suffix = True
    montgomery_form_a = True
    disallow_zero_a = True

    def result(self) -> List[str]:
        result = bignum_common.invmod_positive(self.int_a, self.int_n)
        mont_result = self.to_montgomery(result)
        return [self.format_result(mont_result)]


class BignumModRawAdd(bignum_common.ModOperationCommon,
                      BignumModRawTarget):
    """Test cases for bignum mpi_mod_raw_add()."""
    symbol = "+"
    test_function = "mpi_mod_raw_add"
    test_name = "mbedtls_mpi_mod_raw_add"
    input_style = "fixed"
    arity = 2

    def result(self) -> List[str]:
        result = (self.int_a + self.int_b) % self.int_n
        return [self.format_result(result)]


class BignumModRawConvertRep(bignum_common.ModOperationCommon,
                             BignumModRawTarget):
    # This is an abstract class, it's ok to have unimplemented methods.
    #pylint: disable=abstract-method
    """Test cases for representation conversion."""
    symbol = ""
    input_style = "arch_split"
    arity = 1
    rep = bignum_common.ModulusRepresentation.INVALID

    def set_representation(self, r: bignum_common.ModulusRepresentation) -> None:
        self.rep = r

    def arguments(self) -> List[str]:
        return ([bignum_common.quote_str(self.arg_n), self.rep.symbol(),
                 bignum_common.quote_str(self.arg_a)] +
                self.result())

    def description(self) -> str:
        base = super().description()
        mod_with_rep = 'mod({})'.format(self.rep.name)
        return base.replace('mod', mod_with_rep, 1)

    @classmethod
    def test_cases_for_values(cls, rep: bignum_common.ModulusRepresentation,
                              n: str, a: str) -> Iterator[test_case.TestCase]:
        """Emit test cases for the given values (if any).

        This may emit no test cases if a isn't valid for the modulus n,
        or multiple test cases if rep requires different data depending
        on the limb size.
        """
        for bil in cls.limb_sizes:
            test_object = cls(n, a, bits_in_limb=bil)
            test_object.set_representation(rep)
            # The class is set to having separate test cases for each limb
            # size, because the Montgomery representation requires it.
            # But other representations don't require it. So for other
            # representations, emit a single test case with no dependency
            # on the limb size.
            if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
                test_object.dependencies = \
                    [dep for dep in test_object.dependencies
                     if not dep.startswith('MBEDTLS_HAVE_INT')]
            if test_object.is_valid:
                yield test_object.create_test_case()
            if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
                # A single test case (emitted, or skipped due to invalidity)
                # is enough, since this test case doesn't depend on the
                # limb size.
                break

    # The parent class doesn't support non-bignum parameters. So we override
    # test generation, in order to have the representation as a parameter.
    @classmethod
    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:

        for rep in bignum_common.ModulusRepresentation.supported_representations():
            for n in cls.moduli:
                for a in cls.input_values:
                    yield from cls.test_cases_for_values(rep, n, a)

class BignumModRawCanonicalToModulusRep(BignumModRawConvertRep):
    """Test cases for mpi_mod_raw_canonical_to_modulus_rep."""
    test_function = "mpi_mod_raw_canonical_to_modulus_rep"
    test_name = "Rep canon->mod"

    def result(self) -> List[str]:
        return [self.format_result(self.convert_from_canonical(self.int_a, self.rep))]

class BignumModRawModulusToCanonicalRep(BignumModRawConvertRep):
    """Test cases for mpi_mod_raw_modulus_to_canonical_rep."""
    test_function = "mpi_mod_raw_modulus_to_canonical_rep"
    test_name = "Rep mod->canon"

    @property
    def arg_a(self) -> str:
        return self.format_arg("{:x}".format(self.convert_from_canonical(self.int_a, self.rep)))

    def result(self) -> List[str]:
        return [self.format_result(self.int_a)]


class BignumModRawConvertToMont(bignum_common.ModOperationCommon,
                                BignumModRawTarget):
    """ Test cases for mpi_mod_raw_to_mont_rep(). """
    test_function = "mpi_mod_raw_to_mont_rep"
    test_name = "Convert into Mont: "
    symbol = "R *"
    input_style = "arch_split"
    arity = 1

    def result(self) -> List[str]:
        result = self.to_montgomery(self.int_a)
        return [self.format_result(result)]

class BignumModRawConvertFromMont(bignum_common.ModOperationCommon,
                                  BignumModRawTarget):
    """ Test cases for mpi_mod_raw_from_mont_rep(). """
    test_function = "mpi_mod_raw_from_mont_rep"
    test_name = "Convert from Mont: "
    symbol = "1/R *"
    input_style = "arch_split"
    arity = 1

    def result(self) -> List[str]:
        result = self.from_montgomery(self.int_a)
        return [self.format_result(result)]

class BignumModRawModNegate(bignum_common.ModOperationCommon,
                            BignumModRawTarget):
    """ Test cases for mpi_mod_raw_neg(). """
    test_function = "mpi_mod_raw_neg"
    test_name = "Modular negation: "
    symbol = "-"
    input_style = "arch_split"
    arity = 1

    def result(self) -> List[str]:
        result = (self.int_n - self.int_a) % self.int_n
        return [self.format_result(result)]