Coverage Report

Created: 2023-09-25 06:34

/src/cryptofuzz/tests.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "tests.h"
2
#include <fuzzing/datasource/id.hpp>
3
#include <cryptofuzz/repository.h>
4
#include <cryptofuzz/util.h>
5
#include <boost/multiprecision/cpp_int.hpp>
6
#include <iostream>
7
8
namespace cryptofuzz {
9
namespace tests {
10
11
template <class ResultType, class OperationType>
12
15.3k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
15.3k
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
15.3k
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_SCRYPT>(cryptofuzz::operation::KDF_SCRYPT const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
1.02k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
1.02k
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
1.02k
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_HKDF>(cryptofuzz::operation::KDF_HKDF const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
5.49k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
5.49k
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
5.49k
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_TLS1_PRF>(cryptofuzz::operation::KDF_TLS1_PRF const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
723
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
723
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
723
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_PBKDF>(cryptofuzz::operation::KDF_PBKDF const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
624
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
624
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
624
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_PBKDF1>(cryptofuzz::operation::KDF_PBKDF1 const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
534
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
534
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
534
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_PBKDF2>(cryptofuzz::operation::KDF_PBKDF2 const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
2.57k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
2.57k
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
2.57k
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_ARGON2>(cryptofuzz::operation::KDF_ARGON2 const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
892
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
892
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
892
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_SSH>(cryptofuzz::operation::KDF_SSH const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
630
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
630
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
630
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_X963>(cryptofuzz::operation::KDF_X963 const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
554
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
554
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
554
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_BCRYPT>(cryptofuzz::operation::KDF_BCRYPT const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
197
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
197
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
197
}
void cryptofuzz::tests::verifyKeySize<std::__1::optional<cryptofuzz::Buffer>, cryptofuzz::operation::KDF_SP_800_108>(cryptofuzz::operation::KDF_SP_800_108 const&, std::__1::optional<cryptofuzz::Buffer> const&)
Line
Count
Source
12
2.12k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
2.12k
    if ( result != std::nullopt && op.keySize != result->GetSize() ) {
14
        /* TODO include module name in abort message */
15
0
        util::abort({op.Name(), "invalid keySize"});
16
0
    }
17
2.12k
}
18
19
4.91k
static void checkZeroResult(const std::optional<Buffer>& b) {
20
4.91k
    if ( b == std::nullopt ) {
21
0
        return;
22
0
    }
23
24
4.91k
    if ( b->GetSize() >= 16 ) {
25
4.10k
        const std::vector<uint8_t> zeroes(b->GetSize(), 0);
26
4.10k
        if ( b->Get() == zeroes ) {
27
0
            printf("An all-zero hash was returned. This might indicate a bug.\n");
28
0
            abort();
29
0
        }
30
4.10k
    }
31
4.91k
}
32
33
6.60k
void test(const operation::Digest& op, const std::optional<component::Digest>& result) {
34
6.60k
    if ( result == std::nullopt ) {
35
3.10k
        return;
36
3.10k
    }
37
38
3.49k
    {
39
3.49k
        const auto expectedSize = repository::DigestSize(op.digestType.Get());
40
41
3.49k
        if ( expectedSize != std::nullopt ) {
42
3.21k
            if ( result->GetSize() != *expectedSize ) {
43
0
                printf("Expected vs actual digest size: %zu / %zu\n", *expectedSize, result->GetSize());
44
0
                abort();
45
0
            }
46
3.21k
        }
47
3.49k
    }
48
49
3.49k
    checkZeroResult(result);
50
3.49k
}
51
52
4.04k
void test(const operation::HMAC& op, const std::optional<component::MAC>& result) {
53
4.04k
    if ( result == std::nullopt ) {
54
2.62k
        return;
55
2.62k
    }
56
57
1.41k
    {
58
1.41k
        const auto expectedSize = repository::DigestSize(op.digestType.Get());
59
60
1.41k
        if ( expectedSize != std::nullopt ) {
61
1.02k
            if ( result->GetSize() != *expectedSize ) {
62
0
                printf("Expected vs actual digest size: %zu / %zu\n", *expectedSize, result->GetSize());
63
0
                abort();
64
0
            }
65
1.02k
        }
66
1.41k
    }
67
68
1.41k
    checkZeroResult(result);
69
1.41k
}
70
71
3.93k
void test(const operation::UMAC& op, const std::optional<component::MAC>& result) {
72
3.93k
    if ( result == std::nullopt ) {
73
1.95k
        return;
74
1.95k
    }
75
76
1.97k
    if (
77
1.97k
            ( op.type == 0 && result->GetSize() > (32/8) ) ||
78
1.97k
            ( op.type == 1 && result->GetSize() > (64/8) ) ||
79
1.97k
            ( op.type == 2 && result->GetSize() > (96/8) ) ||
80
1.97k
            ( op.type == 3 && result->GetSize() > (128/8) )
81
1.97k
    ) {
82
0
        printf("UMAC: Overlong result: %zu\n", result->GetSize());
83
0
        abort();
84
0
    }
85
1.97k
}
86
87
22.6k
static void test_ChaCha20_Poly1305_IV(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
88
22.6k
    using fuzzing::datasource::ID;
89
90
    /*
91
     * OpenSSL CVE-2019-1543
92
     * https://www.openssl.org/news/secadv/20190306.txt
93
     */
94
95
22.6k
    if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20_POLY1305") ) {
96
21.9k
        return;
97
21.9k
    }
98
99
704
    if ( result == std::nullopt ) {
100
540
        return;
101
540
    }
102
103
164
    if ( op.cipher.iv.GetSize() > 12 ) {
104
0
        abort();
105
0
    }
106
164
}
107
108
22.6k
static void test_XChaCha20_Poly1305_IV(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
109
22.6k
    using fuzzing::datasource::ID;
110
111
22.6k
    if ( op.cipher.cipherType.Get() != CF_CIPHER("XCHACHA20_POLY1305") ) {
112
22.5k
        return;
113
22.5k
    }
114
115
71
    if ( result == std::nullopt ) {
116
71
        return;
117
71
    }
118
119
0
    if ( op.cipher.iv.GetSize() != 24 ) {
120
0
        printf("XChaCha20-Poly1305 succeeded with an IV of %zu bytes large, but only IVs of 24 bytes are valid\n", op.cipher.iv.GetSize());
121
0
        abort();
122
0
    }
123
0
}
124
125
22.6k
static void test_AES_CCM_Wycheproof(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
126
22.6k
    bool fail = false;
127
128
22.6k
    if ( result == std::nullopt ) {
129
14.1k
        return;
130
14.1k
    }
131
132
8.49k
    switch ( op.cipher.cipherType.Get() ) {
133
154
        case CF_CIPHER("AES_128_CCM"):
134
258
        case CF_CIPHER("AES_192_CCM"):
135
444
        case CF_CIPHER("AES_256_CCM"):
136
444
            break;
137
8.05k
        default:
138
8.05k
            return;
139
8.49k
    }
140
141
444
    if ( op.cipher.iv.GetSize() < 7 || op.cipher.iv.GetSize() > 13 ) {
142
0
        printf("AES CCM: Invalid IV size\n");
143
0
        fail = true;
144
0
    }
145
146
444
    if ( result->tag != std::nullopt ) {
147
444
        static const std::vector<size_t> validTagSizes = {4, 6, 8, 10, 12, 14, 16};
148
149
444
        if ( std::find(validTagSizes.begin(), validTagSizes.end(), result->tag->GetSize()) == validTagSizes.end() ) {
150
0
            printf("AES CCM: Invalid tag size\n");
151
0
            fail = true;
152
0
        }
153
444
    }
154
155
444
    if ( fail == true ) {
156
0
        printf("AES CCM tests based on Wycheproof: https://github.com/google/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/aes_ccm_test.json#L11\n");
157
0
        abort();
158
0
    }
159
444
}
160
161
22.6k
static void test_AES_GCM_Wycheproof(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
162
22.6k
    bool fail = false;
163
164
22.6k
    if ( result == std::nullopt ) {
165
14.1k
        return;
166
14.1k
    }
167
168
8.49k
    switch ( op.cipher.cipherType.Get() ) {
169
371
        case CF_CIPHER("AES_128_GCM"):
170
578
        case CF_CIPHER("AES_192_GCM"):
171
792
        case CF_CIPHER("AES_256_GCM"):
172
792
            break;
173
7.70k
        default:
174
7.70k
            return;
175
8.49k
    }
176
177
792
    if ( op.cipher.iv.GetSize() == 0 ) {
178
0
        printf("AES GCM: Invalid IV size\n");
179
0
        fail = true;
180
0
    }
181
182
792
    if ( fail == true ) {
183
0
        printf("AES GCM tests based on Wycheproof: https://github.com/google/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/aes_gcm_test.json#L13\n");
184
0
        abort();
185
0
    }
186
792
}
187
188
22.6k
void test(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
189
22.6k
    test_ChaCha20_Poly1305_IV(op, result);
190
22.6k
    test_XChaCha20_Poly1305_IV(op, result);
191
22.6k
    test_AES_CCM_Wycheproof(op, result);
192
22.6k
    test_AES_GCM_Wycheproof(op, result);
193
22.6k
}
194
195
12.7k
void test(const operation::SymmetricDecrypt& op, const std::optional<component::Cleartext>& result) {
196
12.7k
    (void)op;
197
12.7k
    (void)result;
198
12.7k
}
199
200
4.88k
void test(const operation::CMAC& op, const std::optional<component::MAC>& result) {
201
4.88k
    (void)op;
202
4.88k
    (void)result;
203
4.88k
}
204
205
1.02k
void test(const operation::KDF_SCRYPT& op, const std::optional<component::Key>& result) {
206
1.02k
    verifyKeySize(op, result);
207
1.02k
}
208
209
5.49k
static void test_HKDF_OutputSize(const operation::KDF_HKDF& op, const std::optional<component::Key>& result) {
210
5.49k
    if ( result == std::nullopt ) {
211
2.32k
        return;
212
2.32k
    }
213
214
3.16k
    const auto expectedSize = repository::DigestSize(op.digestType.Get());
215
216
3.16k
    if ( expectedSize == std::nullopt ) {
217
262
        return;
218
262
    }
219
220
2.90k
    const size_t maxOutputSize = 255 * *expectedSize;
221
222
2.90k
    if ( result->GetSize() > maxOutputSize ) {
223
0
        printf("The output size of HKDF (%zu) is more than 255 * the size of the hash digest (%zu)\n", result->GetSize(), maxOutputSize);
224
0
        abort();
225
0
    }
226
2.90k
}
227
228
5.49k
void test(const operation::KDF_HKDF& op, const std::optional<component::Key>& result) {
229
5.49k
    verifyKeySize(op, result);
230
231
5.49k
    test_HKDF_OutputSize(op, result);
232
5.49k
}
233
234
723
void test(const operation::KDF_TLS1_PRF& op, const std::optional<component::Key>& result) {
235
723
    verifyKeySize(op, result);
236
723
}
237
238
624
void test(const operation::KDF_PBKDF& op, const std::optional<component::Key>& result) {
239
624
    verifyKeySize(op, result);
240
624
}
241
242
534
void test(const operation::KDF_PBKDF1& op, const std::optional<component::Key>& result) {
243
534
    verifyKeySize(op, result);
244
534
}
245
246
2.57k
void test(const operation::KDF_PBKDF2& op, const std::optional<component::Key>& result) {
247
2.57k
    verifyKeySize(op, result);
248
2.57k
}
249
250
892
void test(const operation::KDF_ARGON2& op, const std::optional<component::Key>& result) {
251
892
    verifyKeySize(op, result);
252
892
}
253
254
630
void test(const operation::KDF_SSH& op, const std::optional<component::Key>& result) {
255
630
    verifyKeySize(op, result);
256
630
}
257
258
554
void test(const operation::KDF_X963& op, const std::optional<component::Key>& result) {
259
554
    verifyKeySize(op, result);
260
554
}
261
262
197
void test(const operation::KDF_BCRYPT& op, const std::optional<component::Key>& result) {
263
197
    verifyKeySize(op, result);
264
197
}
265
266
2.12k
void test(const operation::KDF_SP_800_108& op, const std::optional<component::Key>& result) {
267
2.12k
    verifyKeySize(op, result);
268
2.12k
}
269
270
1.98k
static bool IsSpecialCurve(const uint64_t curveID) {
271
1.98k
    switch ( curveID ) {
272
0
        case CF_ECC_CURVE("ed448"):
273
399
        case CF_ECC_CURVE("ed25519"):
274
399
        case CF_ECC_CURVE("x25519"):
275
399
        case CF_ECC_CURVE("x448"):
276
399
            return true;
277
1.58k
        default:
278
1.58k
            return false;
279
1.98k
    }
280
1.98k
}
281
282
2.57k
static void test_ECC_PrivateKey(const uint64_t curveID, const std::string priv) {
283
    /* Disabled until all modules comply by default */
284
2.57k
    return;
285
286
    /* Private key may be 0 with these curves */
287
0
    if ( IsSpecialCurve(curveID) ) {
288
0
        return;
289
0
    }
290
291
0
    if ( priv == "0" ) {
292
0
        std::cout << "0 is an invalid elliptic curve private key" << std::endl;
293
0
        ::abort();
294
0
    }
295
0
}
296
297
298
2.29k
void test(const operation::ECC_PrivateToPublic& op, const std::optional<component::ECC_PublicKey>& result) {
299
2.29k
    if ( result != std::nullopt ) {
300
977
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
301
977
    }
302
2.29k
}
303
304
2.04k
void test(const operation::ECC_ValidatePubkey& op, const std::optional<bool>& result) {
305
2.04k
    (void)op;
306
2.04k
    (void)result;
307
2.04k
}
308
309
1.86k
void test(const operation::ECC_GenerateKeyPair& op, const std::optional<component::ECC_KeyPair>& result) {
310
1.86k
    if ( result != std::nullopt ) {
311
435
        test_ECC_PrivateKey(op.curveType.Get(), result->priv.ToTrimmedString());
312
435
    }
313
1.86k
}
314
315
1.93k
static void test_ECDSA_Signature(const uint64_t curveID, const std::string R, const std::string S) {
316
1.93k
    if ( IsSpecialCurve(curveID) ) {
317
346
        return;
318
346
    }
319
320
1.58k
    const boost::multiprecision::cpp_int r(R), s(S);
321
322
1.58k
    if ( r < 1 ) {
323
0
        std::cout << "ECDSA signature invalid: R < 1" << std::endl;
324
0
        ::abort();
325
0
    }
326
1.58k
    if ( s < 1 ) {
327
0
        std::cout << "ECDSA signature invalid: S < 1" << std::endl;
328
0
        ::abort();
329
0
    }
330
331
1.58k
    const auto O = cryptofuzz::repository::ECC_CurveToOrder(curveID);
332
1.58k
    if ( O == std::nullopt ) {
333
211
        return;
334
211
    }
335
336
1.37k
    const boost::multiprecision::cpp_int o(*O);
337
338
1.37k
    if ( r >= o ) {
339
0
        std::cout << "ECDSA signature invalid: R >= order" << std::endl;
340
0
        ::abort();
341
0
    }
342
343
1.37k
    if ( s >= o ) {
344
0
        std::cout << "ECDSA signature invalid: S >= order" << std::endl;
345
0
        ::abort();
346
0
    }
347
1.37k
}
348
349
0
static void test_BIP340_Schnorr_Signature(const uint64_t curveID, const std::string R, const std::string S) {
350
0
    boost::multiprecision::cpp_int r(R);
351
0
    boost::multiprecision::cpp_int s(S);
352
0
    if ( r < 1 ) {
353
0
        std::cout << "BIP340 Schnorr signature invalid: R < 1" << std::endl;
354
0
        ::abort();
355
0
    }
356
0
    if ( s < 1 ) {
357
0
        std::cout << "BIP340 Schnorr signature invalid: S < 1" << std::endl;
358
0
        ::abort();
359
0
    }
360
361
0
    const auto prime = cryptofuzz::repository::ECC_CurveToPrime(curveID);
362
0
    if ( prime != std::nullopt ) {
363
0
        const boost::multiprecision::cpp_int p(*prime);
364
0
        CF_ASSERT(r < p, "BIP340 Schnorr signature R should be less than curve P");
365
0
    }
366
367
0
    const auto order = cryptofuzz::repository::ECC_CurveToOrder(curveID);
368
0
    if ( order != std::nullopt ) {
369
0
        const boost::multiprecision::cpp_int n(*order);
370
0
        CF_ASSERT(s < n, "BIP340 Schnorr signature S should be less than curve N");
371
0
    }
372
0
}
373
374
200
void test(const operation::ECCSI_Sign& op, const std::optional<component::ECCSI_Signature>& result) {
375
200
    (void)op;
376
200
    (void)result;
377
200
}
378
2.30k
void test(const operation::ECDSA_Sign& op, const std::optional<component::ECDSA_Signature>& result) {
379
2.30k
    if ( result != std::nullopt ) {
380
1.07k
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
381
382
1.07k
        if (
383
1.07k
                op.UseSpecifiedNonce() == true &&
384
1.07k
                !IsSpecialCurve(op.curveType.Get()) &&
385
1.07k
                op.nonce.ToTrimmedString() == "0"
386
1.07k
           ) {
387
0
            std::cout << "0 is an invalid ECDSA nonce" << std::endl;
388
0
            ::abort();
389
0
        }
390
391
1.07k
        test_ECDSA_Signature(op.curveType.Get(),
392
1.07k
                result->signature.first.ToTrimmedString(),
393
1.07k
                result->signature.second.ToTrimmedString());
394
1.07k
    }
395
2.30k
}
396
397
536
void test(const operation::ECGDSA_Sign& op, const std::optional<component::ECGDSA_Signature>& result) {
398
536
    if ( result != std::nullopt ) {
399
88
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
400
401
88
        if (
402
88
                op.UseSpecifiedNonce() == true &&
403
88
                !IsSpecialCurve(op.curveType.Get()) &&
404
88
                op.nonce.ToTrimmedString() == "0"
405
88
           ) {
406
0
            std::cout << "0 is an invalid ECGDSA nonce" << std::endl;
407
0
            ::abort();
408
0
        }
409
410
88
        test_ECDSA_Signature(op.curveType.Get(),
411
88
                result->signature.first.ToTrimmedString(),
412
88
                result->signature.second.ToTrimmedString());
413
88
    }
414
536
}
415
416
174
void test(const operation::ECRDSA_Sign& op, const std::optional<component::ECRDSA_Signature>& result) {
417
174
    if ( result != std::nullopt ) {
418
0
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
419
420
0
        if (
421
0
                op.UseSpecifiedNonce() == true &&
422
0
                !IsSpecialCurve(op.curveType.Get()) &&
423
0
                op.nonce.ToTrimmedString() == "0"
424
0
           ) {
425
0
            std::cout << "0 is an invalid ECRDSA nonce" << std::endl;
426
0
            ::abort();
427
0
        }
428
429
0
        test_ECDSA_Signature(op.curveType.Get(),
430
0
                result->signature.first.ToTrimmedString(),
431
0
                result->signature.second.ToTrimmedString());
432
0
    }
433
174
}
434
435
207
void test(const operation::Schnorr_Sign& op, const std::optional<component::Schnorr_Signature>& result) {
436
207
    if ( result != std::nullopt ) {
437
0
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
438
439
0
        if (
440
0
                op.UseSpecifiedNonce() == true &&
441
0
                !IsSpecialCurve(op.curveType.Get()) &&
442
0
                op.nonce.ToTrimmedString() == "0"
443
0
           ) {
444
0
            std::cout << "0 is an invalid Schnorr nonce" << std::endl;
445
0
            ::abort();
446
0
        }
447
448
0
        test_BIP340_Schnorr_Signature(op.curveType.Get(),
449
0
                result->signature.first.ToTrimmedString(),
450
0
                result->signature.second.ToTrimmedString());
451
0
    }
452
207
}
453
454
162
void test(const operation::ECCSI_Verify& op, const std::optional<bool>& result) {
455
162
    (void)op;
456
162
    (void)result;
457
162
}
458
459
1.10k
void test(const operation::ECDSA_Verify& op, const std::optional<bool>& result) {
460
1.10k
    if ( result != std::nullopt && *result == true ) {
461
35
        test_ECDSA_Signature(op.curveType.Get(),
462
35
                op.signature.signature.first.ToTrimmedString(),
463
35
                op.signature.signature.second.ToTrimmedString());
464
35
    }
465
1.10k
}
466
467
595
void test(const operation::ECGDSA_Verify& op, const std::optional<bool>& result) {
468
595
    if ( result != std::nullopt && *result == true ) {
469
11
        test_ECDSA_Signature(op.curveType.Get(),
470
11
                op.signature.signature.first.ToTrimmedString(),
471
11
                op.signature.signature.second.ToTrimmedString());
472
11
    }
473
595
}
474
475
140
void test(const operation::ECRDSA_Verify& op, const std::optional<bool>& result) {
476
140
    if ( result != std::nullopt && *result == true ) {
477
0
        test_ECDSA_Signature(op.curveType.Get(),
478
0
                op.signature.signature.first.ToTrimmedString(),
479
0
                op.signature.signature.second.ToTrimmedString());
480
0
    }
481
140
}
482
483
156
void test(const operation::Schnorr_Verify& op, const std::optional<bool>& result) {
484
156
    if ( result != std::nullopt && *result == true ) {
485
0
        test_BIP340_Schnorr_Signature(op.curveType.Get(),
486
0
                op.signature.signature.first.ToTrimmedString(),
487
0
                op.signature.signature.second.ToTrimmedString());
488
0
    }
489
156
}
490
491
1.74k
void test(const operation::ECDSA_Recover& op, const std::optional<component::ECC_PublicKey>& result) {
492
1.74k
    if ( result != std::nullopt ) {
493
723
        if ( op.id > 3 ) {
494
0
            std::cout << "Invalid recovery ID" << std::endl;
495
0
            ::abort();
496
0
        }
497
723
    }
498
1.74k
    if ( result != std::nullopt ) {
499
723
        test_ECDSA_Signature(op.curveType.Get(),
500
723
                op.signature.first.ToTrimmedString(),
501
723
                op.signature.second.ToTrimmedString());
502
723
    }
503
1.74k
}
504
505
868
void test(const operation::DSA_Verify& op, const std::optional<bool>& result) {
506
868
    (void)op;
507
508
868
    if ( result == std::nullopt || *result == false ) {
509
814
        return;
510
814
    }
511
512
54
    if ( !op.signature.first.IsPositive() ) {
513
0
        std::cout << "DSA signature must be rejected if R is smaller than 1" << std::endl;
514
0
        ::abort();
515
0
    }
516
54
    if ( !op.signature.second.IsPositive() ) {
517
0
        std::cout << "DSA signature must be rejected is S is smaller than 1" << std::endl;
518
0
        ::abort();
519
0
    }
520
521
    /* Q > R */
522
54
    if ( op.signature.first.ToTrimmedString().size() > op.parameters.q.ToTrimmedString().size() ) {
523
0
        std::cout << "DSA signature must be rejected if R is larger than Q" << std::endl;
524
0
        ::abort();
525
0
    }
526
    /* Q > S */
527
54
    if ( op.signature.second.ToTrimmedString().size() > op.parameters.q.ToTrimmedString().size() ) {
528
0
        std::cout << "DSA signature must be rejected if S is larger than Q" << std::endl;
529
0
        ::abort();
530
0
    }
531
54
}
532
533
268
void test(const operation::DSA_Sign& op, const std::optional<component::DSA_Signature>& result) {
534
268
    if ( result == std::nullopt ) {
535
268
        return;
536
268
    }
537
538
0
    if ( !result->signature.first.IsPositive() ) {
539
0
        std::cout << "DSA signature R must be larger than 0" << std::endl;
540
0
        ::abort();
541
0
    }
542
0
    if ( !result->signature.second.IsPositive() ) {
543
0
        std::cout << "DSA signature S must be larger than 0" << std::endl;
544
0
        ::abort();
545
0
    }
546
547
    /* Q > R */
548
0
    if ( result->signature.first.ToTrimmedString().size() > op.parameters.q.ToTrimmedString().size() ) {
549
0
        std::cout << "DSA signature R must be smaller than P" << std::endl;
550
0
        ::abort();
551
0
    }
552
    /* Q > S */
553
0
    if ( result->signature.second.ToTrimmedString().size() > op.parameters.q.ToTrimmedString().size() ) {
554
0
        std::cout << "DSA signature S must be smaller than Q" << std::endl;
555
0
        ::abort();
556
0
    }
557
558
    /* R > 0 */
559
0
    if ( !result->signature.first.IsPositive() ) {
560
0
        std::cout << "DSA signature R must be larger than 0" << std::endl;
561
0
        ::abort();
562
0
    }
563
    /* S > 0 */
564
0
    if ( !result->signature.second.IsPositive() ) {
565
0
        std::cout << "DSA signature R must be larger than 0" << std::endl;
566
0
        ::abort();
567
0
    }
568
0
}
569
570
0
static bool isComposite(const std::string &num) {
571
0
    if ( num.size() == 0 ) {
572
0
        return true;
573
0
    }
574
575
0
    size_t sum = 0;
576
0
    for (char c : num) {
577
0
        sum += c - '0';
578
0
    }
579
0
    if (sum % 3 == 0) {
580
0
        return true;
581
0
    }
582
583
0
    return false;
584
0
}
585
586
587
149
void test(const operation::DSA_GenerateParameters& op, const std::optional<component::DSA_Parameters>& result) {
588
149
    (void)op;
589
590
149
    if ( result == std::nullopt ) {
591
149
        return;
592
149
    }
593
594
    /* Larger than 0 */
595
0
    if ( !result->p.IsPositive() ) {
596
0
        std::cout << "DSA P parameter must be larger than 0" << std::endl;
597
0
        ::abort();
598
0
    }
599
0
    if ( !result->q.IsPositive() ) {
600
0
        std::cout << "DSA Q parameter must be larger than 0" << std::endl;
601
0
        ::abort();
602
0
    }
603
0
    if ( !result->g.IsPositive() ) {
604
0
        std::cout << "DSA G parameter must be larger than 0" << std::endl;
605
0
        ::abort();
606
0
    }
607
608
    /* P > Q */
609
0
    if ( result->q.ToTrimmedString().size() > result->p.ToTrimmedString().size() ) {
610
0
        std::cout << "DSA Q must be smaller than P" << std::endl;
611
0
        ::abort();
612
0
    }
613
614
    /* P > G */
615
0
    if ( result->q.ToTrimmedString().size() > result->p.ToTrimmedString().size() ) {
616
0
        std::cout << "DSA G must be smaller than P" << std::endl;
617
0
        ::abort();
618
0
    }
619
620
    /* G != 1 */
621
0
    if ( result->p.ToTrimmedString() == "1" ) {
622
0
        std::cout << "DSA G must not be 1" << std::endl;
623
0
        ::abort();
624
0
    }
625
626
    /* P, Q must be prime */
627
0
    if ( isComposite(result->p.ToTrimmedString()) ) {
628
0
        std::cout << "DSA P must be prime" << std::endl;
629
0
        ::abort();
630
0
    }
631
632
0
    if ( isComposite(result->q.ToTrimmedString()) ) {
633
0
        std::cout << "DSA Q must be prime" << std::endl;
634
0
        ::abort();
635
0
    }
636
0
}
637
638
150
void test(const operation::DSA_PrivateToPublic& op, const std::optional<component::Bignum>& result) {
639
150
    (void)op;
640
150
    (void)result;
641
150
}
642
643
250
void test(const operation::DSA_GenerateKeyPair& op, const std::optional<component::DSA_KeyPair>& result) {
644
250
    if ( result == std::nullopt ) {
645
250
        return;
646
250
    }
647
648
0
    if ( !result->first.IsPositive() ) {
649
0
        std::cout << "Private key must be larger than 0" << std::endl;
650
0
        ::abort();
651
0
    }
652
653
    /* Q > priv */
654
0
    if ( result->first.ToTrimmedString().size() > op.q.ToTrimmedString().size() ) {
655
0
        std::cout << "Q must be larger than private key" << std::endl;
656
0
        ::abort();
657
0
    }
658
0
}
659
660
161
void test(const operation::ECDH_Derive& op, const std::optional<component::Secret>& result) {
661
161
    (void)op;
662
161
    (void)result;
663
161
}
664
665
204
void test(const operation::ECIES_Encrypt& op, const std::optional<component::Ciphertext>& result) {
666
    /* TODO check minimum size? */
667
204
    (void)op;
668
204
    (void)result;
669
204
}
670
671
185
void test(const operation::ECIES_Decrypt& op, const std::optional<component::Cleartext>& result) {
672
185
    (void)op;
673
185
    (void)result;
674
185
}
675
676
329
void test(const operation::ECC_Point_Add& op, const std::optional<component::ECC_Point>& result) {
677
329
    (void)op;
678
329
    (void)result;
679
329
}
680
681
364
void test(const operation::ECC_Point_Sub& op, const std::optional<component::ECC_Point>& result) {
682
364
    if ( result == std::nullopt ) {
683
312
        return;
684
312
    }
685
686
52
    if ( !(op.a.first == op.b.first) ) {
687
49
        return;
688
49
    }
689
690
3
    if ( !(op.a.second == op.b.second) ) {
691
3
        return;
692
3
    }
693
694
0
    if ( !result->first.IsZero() || !result->second.IsZero() ) {
695
0
        std::cout << "Subtracting equal points should result in point at infinity" << std::endl;
696
0
        ::abort();
697
0
    }
698
0
}
699
700
844
void test(const operation::ECC_Point_Mul& op, const std::optional<component::ECC_Point>& result) {
701
844
    (void)op;
702
844
    (void)result;
703
844
}
704
705
317
void test(const operation::ECC_Point_Neg& op, const std::optional<component::ECC_Point>& result) {
706
317
    (void)op;
707
317
    (void)result;
708
317
}
709
710
280
void test(const operation::ECC_Point_Dbl& op, const std::optional<component::ECC_Point>& result) {
711
280
    (void)op;
712
280
    (void)result;
713
280
}
714
715
306
void test(const operation::ECC_Point_Cmp& op, const std::optional<bool>& result) {
716
306
    (void)op;
717
306
    (void)result;
718
306
}
719
720
240
void test(const operation::DH_GenerateKeyPair& op, const std::optional<component::DH_KeyPair>& result) {
721
240
    (void)op;
722
240
    (void)result;
723
240
}
724
725
833
void test(const operation::DH_Derive& op, const std::optional<component::Bignum>& result) {
726
833
    (void)op;
727
833
    (void)result;
728
833
}
729
730
173
void test(const operation::BLS_PrivateToPublic& op, const std::optional<component::BLS_PublicKey>& result) {
731
173
    (void)op;
732
173
    (void)result;
733
173
}
734
735
197
void test(const operation::BLS_PrivateToPublic_G2& op, const std::optional<component::G2>& result) {
736
197
    (void)op;
737
197
    (void)result;
738
197
}
739
740
187
void test(const operation::BLS_Sign& op, const std::optional<component::BLS_Signature>& result) {
741
187
    (void)op;
742
187
    (void)result;
743
187
}
744
745
175
void test(const operation::BLS_Verify& op, const std::optional<bool>& result) {
746
175
    (void)op;
747
175
    (void)result;
748
175
}
749
750
224
void test(const operation::BLS_BatchSign& op, const std::optional<component::BLS_BatchSignature>& result) {
751
224
    (void)op;
752
224
    (void)result;
753
224
}
754
755
200
void test(const operation::BLS_BatchVerify& op, const std::optional<bool>& result) {
756
200
    (void)op;
757
200
    (void)result;
758
200
}
759
760
172
void test(const operation::BLS_Aggregate_G1& op, const std::optional<component::G1>& result) {
761
172
    (void)op;
762
172
    (void)result;
763
172
}
764
765
178
void test(const operation::BLS_Aggregate_G2& op, const std::optional<component::G2>& result) {
766
178
    (void)op;
767
178
    (void)result;
768
178
}
769
770
161
void test(const operation::BLS_Pairing& op, const std::optional<component::Fp12>& result) {
771
161
    (void)op;
772
161
    (void)result;
773
161
}
774
775
160
void test(const operation::BLS_MillerLoop& op, const std::optional<component::Fp12>& result) {
776
160
    (void)op;
777
160
    (void)result;
778
160
}
779
780
245
void test(const operation::BLS_FinalExp& op, const std::optional<component::Fp12>& result) {
781
245
    (void)op;
782
245
    (void)result;
783
245
}
784
785
170
void test(const operation::BLS_HashToG1& op, const std::optional<component::G1>& result) {
786
170
    (void)op;
787
170
    (void)result;
788
170
}
789
790
139
void test(const operation::BLS_HashToG2& op, const std::optional<component::G2>& result) {
791
139
    (void)op;
792
139
    (void)result;
793
139
}
794
795
164
void test(const operation::BLS_MapToG1& op, const std::optional<component::G1>& result) {
796
164
    (void)op;
797
164
    (void)result;
798
164
}
799
800
159
void test(const operation::BLS_MapToG2& op, const std::optional<component::G2>& result) {
801
159
    (void)op;
802
159
    (void)result;
803
159
}
804
805
166
void test(const operation::BLS_IsG1OnCurve& op, const std::optional<bool>& result) {
806
166
    (void)op;
807
166
    (void)result;
808
166
}
809
810
219
void test(const operation::BLS_IsG2OnCurve& op, const std::optional<bool>& result) {
811
219
    (void)op;
812
219
    (void)result;
813
219
}
814
815
158
void test(const operation::BLS_GenerateKeyPair& op, const std::optional<component::BLS_KeyPair>& result) {
816
158
    (void)op;
817
158
    (void)result;
818
158
}
819
820
160
void test(const operation::BLS_Decompress_G1& op, const std::optional<component::G1>& result) {
821
160
    (void)op;
822
160
    (void)result;
823
160
}
824
825
147
void test(const operation::BLS_Compress_G1& op, const std::optional<component::Bignum>& result) {
826
147
    (void)op;
827
147
    (void)result;
828
147
}
829
830
156
void test(const operation::BLS_Decompress_G2& op, const std::optional<component::G2>& result) {
831
156
    (void)op;
832
156
    (void)result;
833
156
}
834
835
179
void test(const operation::BLS_Compress_G2& op, const std::optional<component::G1>& result) {
836
179
    (void)op;
837
179
    (void)result;
838
179
}
839
840
209
void test(const operation::BLS_G1_Add& op, const std::optional<component::G1>& result) {
841
209
    (void)op;
842
209
    (void)result;
843
209
}
844
845
178
void test(const operation::BLS_G1_Mul& op, const std::optional<component::G1>& result) {
846
178
    (void)op;
847
178
    (void)result;
848
178
}
849
850
248
void test(const operation::BLS_G1_IsEq& op, const std::optional<bool>& result) {
851
248
    (void)op;
852
248
    (void)result;
853
248
}
854
855
152
void test(const operation::BLS_G1_Neg& op, const std::optional<component::G1>& result) {
856
152
    (void)op;
857
152
    (void)result;
858
152
}
859
860
261
void test(const operation::BLS_G2_Add& op, const std::optional<component::G2>& result) {
861
261
    (void)op;
862
261
    (void)result;
863
261
}
864
865
252
void test(const operation::BLS_G2_Mul& op, const std::optional<component::G2>& result) {
866
252
    (void)op;
867
252
    (void)result;
868
252
}
869
870
287
void test(const operation::BLS_G2_IsEq& op, const std::optional<bool>& result) {
871
287
    (void)op;
872
287
    (void)result;
873
287
}
874
875
229
void test(const operation::BLS_G2_Neg& op, const std::optional<component::G2>& result) {
876
229
    (void)op;
877
229
    (void)result;
878
229
}
879
880
281
void test(const operation::BLS_G1_MultiExp& op, const std::optional<component::G1>& result) {
881
281
    (void)op;
882
281
    (void)result;
883
281
}
884
885
132
void test(const operation::Misc& op, const std::optional<Buffer>& result) {
886
132
    (void)op;
887
132
    (void)result;
888
132
}
889
890
170
void test(const operation::SR25519_Verify& op, const std::optional<bool>& result) {
891
170
    (void)op;
892
170
    (void)result;
893
170
}
894
895
namespace BignumCalc {
896
0
    static void Abort(const std::string& message, const std::string& opStr) {
897
0
        std::cout << "BignumCalc ( " << opStr << " ): " << message << std::endl;
898
0
        ::abort();
899
0
    }
900
482
    static void AssertBinary(const component::Bignum& result, const std::string& opStr) {
901
482
        const auto resultStr = result.ToTrimmedString();
902
482
        if ( !(resultStr == "0" || resultStr == "1") ) {
903
0
            Abort("Result must be 0 or 1", opStr);
904
0
        }
905
482
    }
906
122
    static void AssertTertiary(const component::Bignum& result, const std::string& opStr) {
907
122
        const auto resultStr = result.ToTrimmedString();
908
122
        if ( !(resultStr == "0" || resultStr == "1" || resultStr == "-1") ) {
909
0
            Abort("Result must be 0 or 1 or -1", opStr);
910
0
        }
911
122
    }
912
0
    static bool IsEqual(const component::Bignum& A, const component::Bignum& B) {
913
0
        return A.ToTrimmedString() == B.ToTrimmedString();
914
0
    }
915
681
    static bool IsZero(const component::Bignum& A) {
916
681
        return A.ToTrimmedString() == "0";
917
681
    }
918
503
    static bool SmallerThan(const component::Bignum& A, const component::Bignum& B) {
919
503
        return A.ToTrimmedString().size() < B.ToTrimmedString().size();
920
503
    }
921
627
    static bool LargerThan(const component::Bignum& A, const component::Bignum& B) {
922
627
        return A.ToTrimmedString().size() > B.ToTrimmedString().size();
923
627
    }
924
849
    static bool IsEqualOrLargerThan(const component::Bignum& A, const component::Bignum& B) {
925
849
        const auto a = A.ToTrimmedString();
926
849
        const auto b = B.ToTrimmedString();
927
849
        if ( a.size() > b.size() ) {
928
0
            return true;
929
0
        }
930
849
        if ( a.size() == b.size() ) {
931
626
            if ( a == b ) {
932
0
                return true;
933
0
            }
934
626
        }
935
849
        return false;
936
849
    }
937
849
    static void AssertModResult(const component::Bignum& result, const component::Bignum& mod, const std::string& opStr) {
938
849
        if ( IsEqualOrLargerThan(result, mod) ) {
939
0
            Abort("Result is equal to or larger than modulo", opStr);
940
0
        }
941
849
    }
942
170
    static void AssertNotSmallerThan(const component::Bignum& result, const component::Bignum& A, const std::string& opStr) {
943
170
        if ( SmallerThan(result, A) ) {
944
0
            Abort("Result is smaller than the input", opStr);
945
0
        }
946
170
    }
947
    static void AssertNotSmallerThan(
948
            const component::Bignum& result,
949
            const component::Bignum& A,
950
            const component::Bignum& B,
951
271
            const std::string& opStr) {
952
271
        if ( SmallerThan(result, A) && SmallerThan(result, B) ) {
953
0
            Abort("Result is smaller than the input", opStr);
954
0
        }
955
271
    }
956
333
    static void AssertNotLargerThan(const component::Bignum& result, const component::Bignum& A, const std::string& opStr) {
957
333
        if ( LargerThan(result, A) ) {
958
0
            Abort("Result is larger than the input", opStr);
959
0
        }
960
333
    }
961
    static void AssertNotLargerThan(
962
            const component::Bignum& result,
963
            const component::Bignum& A,
964
            const component::Bignum& B,
965
119
            const std::string& opStr) {
966
119
        if ( LargerThan(result, A) && LargerThan(result, B) ) {
967
0
            Abort("Result is larger than the input", opStr);
968
0
        }
969
119
    }
970
    static void AssertPositive(
971
            const component::Bignum& result,
972
844
            const std::string& opStr) {
973
844
        if ( !result.IsPositive() ) {
974
0
            Abort("Result is not positive", opStr);
975
0
        }
976
844
    }
977
    static void AssertOdd(
978
            const component::Bignum& result,
979
985
            const std::string& opStr) {
980
985
        if ( !result.IsOdd() ) {
981
0
            Abort("Result is not odd", opStr);
982
0
        }
983
985
    }
984
    static void AssertZero(
985
            const component::Bignum& result,
986
17
            const std::string& opStr) {
987
17
        if ( !result.IsZero() ) {
988
0
            Abort("Result is not zero", opStr);
989
0
        }
990
17
    }
991
}
992
993
21.3k
void test(const operation::BignumCalc& op, const std::optional<component::Bignum>& result) {
994
21.3k
    if ( result == std::nullopt ) {
995
16.2k
        return;
996
16.2k
    }
997
998
5.11k
    using namespace BignumCalc;
999
1000
5.11k
    const auto calcOp = op.calcOp.Get();
1001
1002
5.11k
    if (
1003
5.11k
            calcOp != CF_CALCOP("IsPrime(A)") &&
1004
5.11k
            calcOp != CF_CALCOP("Prime()") ) {
1005
        /* Negative numbers are not supported yet */
1006
3.97k
        if (    op.bn0.IsNegative() ||
1007
3.97k
                op.bn1.IsNegative() ||
1008
3.97k
                op.bn2.IsNegative() ) {
1009
0
            return;
1010
0
        }
1011
3.97k
    }
1012
1013
    /* Modular calculations are not supported yet */
1014
5.11k
    if ( op.modulo != std::nullopt ) {
1015
990
        return;
1016
990
    }
1017
1018
4.12k
    switch ( calcOp ) {
1019
24
        case    CF_CALCOP("Add(A,B)"):
1020
24
            if (    SmallerThan(*result, op.bn0) ||
1021
24
                    SmallerThan(*result, op.bn1) ) {
1022
0
                Abort("Result is smaller than its operands", repository::CalcOpToString(calcOp));
1023
0
            }
1024
24
            break;
1025
157
        case    CF_CALCOP("Div(A,B)"):
1026
157
            if ( IsZero(op.bn1) ) {
1027
0
                Abort("Division by zero should not produce a result", repository::CalcOpToString(calcOp));
1028
0
            }
1029
1030
157
            if ( LargerThan(*result, op.bn0) ) {
1031
0
                Abort("Result is larger than the dividend", repository::CalcOpToString(calcOp));
1032
0
            }
1033
157
            break;
1034
50
        case    CF_CALCOP("Mul(A,B)"):
1035
50
            if ( IsZero(op.bn0) || IsZero(op.bn1) ) {
1036
31
                if ( !IsZero(*result) ) {
1037
0
                    Abort("Result of Mul with zero operand is not zero", repository::CalcOpToString(calcOp));
1038
0
                }
1039
31
            }
1040
50
            break;
1041
126
        case    CF_CALCOP("Mod(A,B)"):
1042
126
            BignumCalc::AssertModResult(*result, op.bn1, "Mod");
1043
126
            break;
1044
489
        case    CF_CALCOP("ExpMod(A,B,C)"):
1045
489
            BignumCalc::AssertModResult(*result, op.bn2, "ExpMod");
1046
489
            break;
1047
65
        case    CF_CALCOP("AddMod(A,B,C)"):
1048
65
            BignumCalc::AssertModResult(*result, op.bn2, "AddMod");
1049
65
            break;
1050
68
        case    CF_CALCOP("SubMod(A,B,C)"):
1051
68
            BignumCalc::AssertModResult(*result, op.bn2, "SubMod");
1052
68
            break;
1053
51
        case    CF_CALCOP("MulMod(A,B,C)"):
1054
51
            BignumCalc::AssertModResult(*result, op.bn2, "MulMod");
1055
51
            break;
1056
50
        case    CF_CALCOP("SqrMod(A,B)"):
1057
50
            BignumCalc::AssertModResult(*result, op.bn1, "SqrMod");
1058
50
            break;
1059
0
        case    CF_CALCOP("SqrtMod(A,B)"):
1060
0
            BignumCalc::AssertModResult(*result, op.bn1, "SqrtMod");
1061
0
            break;
1062
0
        case    CF_CALCOP("ModLShift(A,B,C)"):
1063
0
            BignumCalc::AssertModResult(*result, op.bn2, "ModLShift");
1064
0
            break;
1065
26
        case    CF_CALCOP("Bit(A,B)"):
1066
26
            BignumCalc::AssertBinary(*result, "Bit");
1067
26
            break;
1068
0
        case    CF_CALCOP("IsCoprime(A,B)"):
1069
0
            BignumCalc::AssertBinary(*result, "IsCoprime");
1070
0
            break;
1071
27
        case    CF_CALCOP("IsEq(A,B)"):
1072
27
            BignumCalc::AssertBinary(*result, "IsEq");
1073
27
            break;
1074
15
        case    CF_CALCOP("IsGt(A,B)"):
1075
15
            BignumCalc::AssertBinary(*result, "IsGt");
1076
15
            break;
1077
16
        case    CF_CALCOP("IsGte(A,B)"):
1078
16
            BignumCalc::AssertBinary(*result, "IsGte");
1079
16
            break;
1080
14
        case    CF_CALCOP("IsLt(A,B)"):
1081
14
            BignumCalc::AssertBinary(*result, "IsLt");
1082
14
            break;
1083
12
        case    CF_CALCOP("IsLte(A,B)"):
1084
12
            BignumCalc::AssertBinary(*result, "IsLte");
1085
12
            break;
1086
11
        case    CF_CALCOP("IsEven(A)"):
1087
11
            BignumCalc::AssertBinary(*result, "IsEven");
1088
11
            break;
1089
17
        case    CF_CALCOP("IsOdd(A)"):
1090
17
            BignumCalc::AssertBinary(*result, "IsOdd");
1091
17
            break;
1092
15
        case    CF_CALCOP("IsOne(A)"):
1093
15
            BignumCalc::AssertBinary(*result, "IsOne");
1094
15
            break;
1095
0
        case    CF_CALCOP("IsPow2(A)"):
1096
0
            BignumCalc::AssertBinary(*result, "IsPow2");
1097
0
            break;
1098
296
        case    CF_CALCOP("IsPrime(A)"):
1099
296
            BignumCalc::AssertBinary(*result, "IsPrime");
1100
296
            if ( !op.bn0.IsPositive() ) {
1101
17
                BignumCalc::AssertZero(*result, "IsPrime");
1102
17
            }
1103
296
            if ( result->IsOne() ) {
1104
141
                if ( op.bn0.ToTrimmedString() != "2" ) {
1105
141
                    BignumCalc::AssertOdd(op.bn0, "IsPrime");
1106
141
                }
1107
141
            }
1108
296
            break;
1109
12
        case    CF_CALCOP("IsZero(A)"):
1110
12
            BignumCalc::AssertBinary(*result, "IsZero");
1111
12
            break;
1112
0
        case    CF_CALCOP("IsSquare(A)"):
1113
0
            BignumCalc::AssertBinary(*result, "IsSquare");
1114
0
            break;
1115
0
        case    CF_CALCOP("IsPower(A)"):
1116
0
            BignumCalc::AssertBinary(*result, "IsPower");
1117
0
            break;
1118
11
        case    CF_CALCOP("IsNeg(A)"):
1119
11
            BignumCalc::AssertBinary(*result, "IsNeg");
1120
11
            break;
1121
10
        case    CF_CALCOP("IsNotZero(A)"):
1122
10
            BignumCalc::AssertBinary(*result, "IsNotZero");
1123
10
            break;
1124
19
        case    CF_CALCOP("Cmp(A,B)"):
1125
19
            BignumCalc::AssertTertiary(*result, "Cmp");
1126
19
            break;
1127
59
        case    CF_CALCOP("CmpAbs(A,B)"):
1128
59
            BignumCalc::AssertTertiary(*result, "CmpAbs");
1129
59
            break;
1130
44
        case    CF_CALCOP("Jacobi(A,B)"):
1131
44
            BignumCalc::AssertTertiary(*result, "Jacobi");
1132
44
            break;
1133
31
        case    CF_CALCOP("Sqr(A)"):
1134
31
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1135
31
            break;
1136
86
        case    CF_CALCOP("RShift(A,B)"):
1137
86
            if ( IsZero(op.bn0) || IsZero(op.bn1) ) {
1138
65
                if ( op.bn0.ToTrimmedString() != result->ToTrimmedString() ) {
1139
0
                    Abort("Zero operand should not alter input", repository::CalcOpToString(calcOp));
1140
0
                }
1141
65
            }
1142
1143
86
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1144
86
            break;
1145
35
        case    CF_CALCOP("LShift1(A)"):
1146
35
            if ( IsZero(op.bn0) ) {
1147
18
                if ( op.bn0.ToTrimmedString() != result->ToTrimmedString() ) {
1148
0
                    Abort("Zero input should remain zero", repository::CalcOpToString(calcOp));
1149
0
                }
1150
18
            }
1151
1152
35
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1153
35
            break;
1154
39
        case    CF_CALCOP("SetBit(A,B)"):
1155
39
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1156
39
            break;
1157
39
        case    CF_CALCOP("ClearBit(A,B)"):
1158
39
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1159
39
            break;
1160
25
        case    CF_CALCOP("Sqrt(A)"):
1161
25
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1162
25
            break;
1163
0
        case    CF_CALCOP("Cbrt(A)"):
1164
0
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1165
0
            break;
1166
65
        case    CF_CALCOP("MulAdd(A,B,C)"):
1167
65
            AssertNotSmallerThan(*result, op.bn2, repository::CalcOpToString(calcOp));
1168
65
            break;
1169
0
        case    CF_CALCOP("Min(A,B)"):
1170
0
        case    CF_CALCOP("Max(A,B)"):
1171
0
            if ( !IsEqual(*result, op.bn0) && !IsEqual(*result, op.bn1) ) {
1172
0
                Abort("Result is not an operand", repository::CalcOpToString(calcOp));
1173
0
            }
1174
0
            break;
1175
0
        case    CF_CALCOP("Mask(A,B)"):
1176
0
            if ( LargerThan(*result, op.bn0) ) {
1177
0
                Abort("Result is larger than input", repository::CalcOpToString(calcOp));
1178
0
            }
1179
0
            break;
1180
0
        case    CF_CALCOP("And(A,B)"):
1181
0
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1182
0
            AssertNotLargerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1183
0
            break;
1184
0
        case    CF_CALCOP("Or(A,B)"):
1185
0
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1186
0
            AssertNotSmallerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1187
0
            break;
1188
0
        case    CF_CALCOP("Nthrt(A,B)"):
1189
0
        case    CF_CALCOP("NthrtRem(A,B)"):
1190
0
            if ( IsZero(op.bn1) ) {
1191
0
                Abort("Root of zero should not produce a result", repository::CalcOpToString(calcOp));
1192
0
            }
1193
0
            break;
1194
0
        case    CF_CALCOP("Zero()"):
1195
0
            if ( !IsZero(*result) ) {
1196
0
                Abort("Result should be zero", repository::CalcOpToString(calcOp));
1197
0
            }
1198
0
            break;
1199
119
        case    CF_CALCOP("GCD(A,B)"):
1200
119
            AssertNotLargerThan(*result, op.bn0, op.bn1, repository::CalcOpToString(calcOp));
1201
119
            break;
1202
271
        case    CF_CALCOP("LCM(A,B)"):
1203
271
            AssertNotSmallerThan(*result, op.bn0, op.bn1, repository::CalcOpToString(calcOp));
1204
271
            break;
1205
235
        case    CF_CALCOP("InvMod(A,B)"):
1206
235
            if ( !IsZero(*result) ) {
1207
158
                AssertNotLargerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1208
158
            }
1209
235
            break;
1210
0
        case    CF_CALCOP("Exp(A,B)"):
1211
0
            AssertNotSmallerThan(*result, op.bn0, op.bn1, repository::CalcOpToString(calcOp));
1212
0
            break;
1213
0
        case    CF_CALCOP("RandMod(A)"):
1214
0
            BignumCalc::AssertModResult(*result, op.bn0, "RandMod");
1215
0
            break;
1216
844
        case    CF_CALCOP("Prime()"):
1217
844
            BignumCalc::AssertPositive(*result, repository::CalcOpToString(calcOp));
1218
844
            if ( result->ToTrimmedString() != "2" ) {
1219
844
                BignumCalc::AssertOdd(*result, repository::CalcOpToString(calcOp));
1220
844
            }
1221
844
            break;
1222
25
        case    CF_CALCOP("RandRange(A,B)"):
1223
25
            AssertNotLargerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1224
25
            break;
1225
4.12k
    }
1226
4.12k
}
1227
1228
304
void test(const operation::BignumCalc_Fp2& op, const std::optional<component::Fp2>& result) {
1229
304
    (void)op;
1230
304
    (void)result;
1231
304
}
1232
1233
844
void test(const operation::BignumCalc_Fp12& op, const std::optional<component::Fp12>& result) {
1234
844
    (void)op;
1235
844
    (void)result;
1236
844
}
1237
1238
} /* namespace tests */
1239
} /* namespace cryptofuzz */