Coverage Report

Created: 2023-02-22 06:14

/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
24.6k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
24.6k
    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
24.6k
}
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.56k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
1.56k
    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.56k
}
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
11.0k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
11.0k
    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
11.0k
}
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
1.05k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
1.05k
    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.05k
}
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
727
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
727
    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
727
}
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
867
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
867
    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
867
}
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
3.30k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
3.30k
    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
3.30k
}
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
1.21k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
1.21k
    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.21k
}
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
816
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
816
    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
816
}
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
763
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
763
    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
763
}
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
299
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
299
    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
299
}
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.97k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
2.97k
    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.97k
}
18
19
6.87k
static void checkZeroResult(const std::optional<Buffer>& b) {
20
6.87k
    if ( b == std::nullopt ) {
21
0
        return;
22
0
    }
23
24
6.87k
    if ( b->GetSize() >= 16 ) {
25
6.04k
        const std::vector<uint8_t> zeroes(b->GetSize(), 0);
26
6.04k
        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
6.04k
    }
31
6.87k
}
32
33
10.7k
void test(const operation::Digest& op, const std::optional<component::Digest>& result) {
34
10.7k
    if ( result == std::nullopt ) {
35
6.20k
        return;
36
6.20k
    }
37
38
4.54k
    {
39
4.54k
        const auto expectedSize = repository::DigestSize(op.digestType.Get());
40
41
4.54k
        if ( expectedSize != std::nullopt ) {
42
4.30k
            if ( result->GetSize() != *expectedSize ) {
43
0
                printf("Expected vs actual digest size: %zu / %zu\n", *expectedSize, result->GetSize());
44
0
                abort();
45
0
            }
46
4.30k
        }
47
4.54k
    }
48
49
4.54k
    checkZeroResult(result);
50
4.54k
}
51
52
5.34k
void test(const operation::HMAC& op, const std::optional<component::MAC>& result) {
53
5.34k
    if ( result == std::nullopt ) {
54
3.01k
        return;
55
3.01k
    }
56
57
2.32k
    {
58
2.32k
        const auto expectedSize = repository::DigestSize(op.digestType.Get());
59
60
2.32k
        if ( expectedSize != std::nullopt ) {
61
1.83k
            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.83k
        }
66
2.32k
    }
67
68
2.32k
    checkZeroResult(result);
69
2.32k
}
70
71
6.06k
void test(const operation::UMAC& op, const std::optional<component::MAC>& result) {
72
6.06k
    if ( result == std::nullopt ) {
73
3.04k
        return;
74
3.04k
    }
75
76
3.01k
    if (
77
3.01k
            ( op.type == 0 && result->GetSize() > (32/8) ) ||
78
3.01k
            ( op.type == 1 && result->GetSize() > (64/8) ) ||
79
3.01k
            ( op.type == 2 && result->GetSize() > (96/8) ) ||
80
3.01k
            ( op.type == 3 && result->GetSize() > (128/8) )
81
3.01k
    ) {
82
0
        printf("UMAC: Overlong result: %zu\n", result->GetSize());
83
0
        abort();
84
0
    }
85
3.01k
}
86
87
27.6k
static void test_ChaCha20_Poly1305_IV(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
88
27.6k
    using fuzzing::datasource::ID;
89
90
    /*
91
     * OpenSSL CVE-2019-1543
92
     * https://www.openssl.org/news/secadv/20190306.txt
93
     */
94
95
27.6k
    if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20_POLY1305") ) {
96
26.7k
        return;
97
26.7k
    }
98
99
823
    if ( result == std::nullopt ) {
100
587
        return;
101
587
    }
102
103
236
    if ( op.cipher.iv.GetSize() > 12 ) {
104
0
        abort();
105
0
    }
106
236
}
107
108
27.6k
static void test_XChaCha20_Poly1305_IV(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
109
27.6k
    using fuzzing::datasource::ID;
110
111
27.6k
    if ( op.cipher.cipherType.Get() != CF_CIPHER("XCHACHA20_POLY1305") ) {
112
27.4k
        return;
113
27.4k
    }
114
115
114
    if ( result == std::nullopt ) {
116
114
        return;
117
114
    }
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
27.6k
static void test_AES_CCM_Wycheproof(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
126
27.6k
    bool fail = false;
127
128
27.6k
    if ( result == std::nullopt ) {
129
18.2k
        return;
130
18.2k
    }
131
132
9.33k
    switch ( op.cipher.cipherType.Get() ) {
133
139
        case CF_CIPHER("AES_128_CCM"):
134
293
        case CF_CIPHER("AES_192_CCM"):
135
379
        case CF_CIPHER("AES_256_CCM"):
136
379
            break;
137
8.96k
        default:
138
8.96k
            return;
139
9.33k
    }
140
141
379
    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
379
    if ( result->tag != std::nullopt ) {
147
379
        static const std::vector<size_t> validTagSizes = {4, 6, 8, 10, 12, 14, 16};
148
149
379
        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
379
    }
154
155
379
    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
379
}
160
161
27.6k
static void test_AES_GCM_Wycheproof(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
162
27.6k
    bool fail = false;
163
164
27.6k
    if ( result == std::nullopt ) {
165
18.2k
        return;
166
18.2k
    }
167
168
9.33k
    switch ( op.cipher.cipherType.Get() ) {
169
313
        case CF_CIPHER("AES_128_GCM"):
170
602
        case CF_CIPHER("AES_192_GCM"):
171
742
        case CF_CIPHER("AES_256_GCM"):
172
742
            break;
173
8.59k
        default:
174
8.59k
            return;
175
9.33k
    }
176
177
742
    if ( op.cipher.iv.GetSize() == 0 ) {
178
0
        printf("AES GCM: Invalid IV size\n");
179
0
        fail = true;
180
0
    }
181
182
742
    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
742
}
187
188
27.6k
void test(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
189
27.6k
    test_ChaCha20_Poly1305_IV(op, result);
190
27.6k
    test_XChaCha20_Poly1305_IV(op, result);
191
27.6k
    test_AES_CCM_Wycheproof(op, result);
192
27.6k
    test_AES_GCM_Wycheproof(op, result);
193
27.6k
}
194
195
21.7k
void test(const operation::SymmetricDecrypt& op, const std::optional<component::Cleartext>& result) {
196
21.7k
    (void)op;
197
21.7k
    (void)result;
198
21.7k
}
199
200
5.95k
void test(const operation::CMAC& op, const std::optional<component::MAC>& result) {
201
5.95k
    (void)op;
202
5.95k
    (void)result;
203
5.95k
}
204
205
1.56k
void test(const operation::KDF_SCRYPT& op, const std::optional<component::Key>& result) {
206
1.56k
    verifyKeySize(op, result);
207
1.56k
}
208
209
11.0k
static void test_HKDF_OutputSize(const operation::KDF_HKDF& op, const std::optional<component::Key>& result) {
210
11.0k
    if ( result == std::nullopt ) {
211
6.49k
        return;
212
6.49k
    }
213
214
4.55k
    const auto expectedSize = repository::DigestSize(op.digestType.Get());
215
216
4.55k
    if ( expectedSize == std::nullopt ) {
217
365
        return;
218
365
    }
219
220
4.18k
    const size_t maxOutputSize = 255 * *expectedSize;
221
222
4.18k
    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
4.18k
}
227
228
11.0k
void test(const operation::KDF_HKDF& op, const std::optional<component::Key>& result) {
229
11.0k
    verifyKeySize(op, result);
230
231
11.0k
    test_HKDF_OutputSize(op, result);
232
11.0k
}
233
234
1.05k
void test(const operation::KDF_TLS1_PRF& op, const std::optional<component::Key>& result) {
235
1.05k
    verifyKeySize(op, result);
236
1.05k
}
237
238
727
void test(const operation::KDF_PBKDF& op, const std::optional<component::Key>& result) {
239
727
    verifyKeySize(op, result);
240
727
}
241
242
867
void test(const operation::KDF_PBKDF1& op, const std::optional<component::Key>& result) {
243
867
    verifyKeySize(op, result);
244
867
}
245
246
3.30k
void test(const operation::KDF_PBKDF2& op, const std::optional<component::Key>& result) {
247
3.30k
    verifyKeySize(op, result);
248
3.30k
}
249
250
1.21k
void test(const operation::KDF_ARGON2& op, const std::optional<component::Key>& result) {
251
1.21k
    verifyKeySize(op, result);
252
1.21k
}
253
254
816
void test(const operation::KDF_SSH& op, const std::optional<component::Key>& result) {
255
816
    verifyKeySize(op, result);
256
816
}
257
258
763
void test(const operation::KDF_X963& op, const std::optional<component::Key>& result) {
259
763
    verifyKeySize(op, result);
260
763
}
261
262
299
void test(const operation::KDF_BCRYPT& op, const std::optional<component::Key>& result) {
263
299
    verifyKeySize(op, result);
264
299
}
265
266
2.97k
void test(const operation::KDF_SP_800_108& op, const std::optional<component::Key>& result) {
267
2.97k
    verifyKeySize(op, result);
268
2.97k
}
269
270
2.86k
static bool IsSpecialCurve(const uint64_t curveID) {
271
2.86k
    switch ( curveID ) {
272
0
        case CF_ECC_CURVE("ed448"):
273
571
        case CF_ECC_CURVE("ed25519"):
274
571
        case CF_ECC_CURVE("x25519"):
275
571
        case CF_ECC_CURVE("x448"):
276
571
            return true;
277
2.29k
        default:
278
2.29k
            return false;
279
2.86k
    }
280
2.86k
}
281
282
3.52k
static void test_ECC_PrivateKey(const uint64_t curveID, const std::string priv) {
283
    /* Disabled until all modules comply by default */
284
3.52k
    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
4.08k
void test(const operation::ECC_PrivateToPublic& op, const std::optional<component::ECC_PublicKey>& result) {
299
4.08k
    if ( result != std::nullopt ) {
300
1.09k
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
301
1.09k
    }
302
4.08k
}
303
304
1.72k
void test(const operation::ECC_ValidatePubkey& op, const std::optional<bool>& result) {
305
1.72k
    (void)op;
306
1.72k
    (void)result;
307
1.72k
}
308
309
2.92k
void test(const operation::ECC_GenerateKeyPair& op, const std::optional<component::ECC_KeyPair>& result) {
310
2.92k
    if ( result != std::nullopt ) {
311
705
        test_ECC_PrivateKey(op.curveType.Get(), result->priv.ToTrimmedString());
312
705
    }
313
2.92k
}
314
315
2.77k
static void test_ECDSA_Signature(const uint64_t curveID, const std::string R, const std::string S) {
316
2.77k
    if ( IsSpecialCurve(curveID) ) {
317
489
        return;
318
489
    }
319
320
2.29k
    const boost::multiprecision::cpp_int r(R), s(S);
321
322
2.29k
    if ( r < 1 ) {
323
0
        std::cout << "ECDSA signature invalid: R < 1" << std::endl;
324
0
        ::abort();
325
0
    }
326
2.29k
    if ( s < 1 ) {
327
0
        std::cout << "ECDSA signature invalid: S < 1" << std::endl;
328
0
        ::abort();
329
0
    }
330
331
2.29k
    const auto O = cryptofuzz::repository::ECC_CurveToOrder(curveID);
332
2.29k
    if ( O == std::nullopt ) {
333
263
        return;
334
263
    }
335
336
2.02k
    const boost::multiprecision::cpp_int o(*O);
337
338
2.02k
    if ( r >= o ) {
339
0
        std::cout << "ECDSA signature invalid: R >= order" << std::endl;
340
0
        ::abort();
341
0
    }
342
343
2.02k
    if ( s >= o ) {
344
0
        std::cout << "ECDSA signature invalid: S >= order" << std::endl;
345
0
        ::abort();
346
0
    }
347
2.02k
}
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
335
void test(const operation::ECCSI_Sign& op, const std::optional<component::ECCSI_Signature>& result) {
375
335
    (void)op;
376
335
    (void)result;
377
335
}
378
3.40k
void test(const operation::ECDSA_Sign& op, const std::optional<component::ECDSA_Signature>& result) {
379
3.40k
    if ( result != std::nullopt ) {
380
1.58k
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
381
382
1.58k
        if (
383
1.58k
                op.UseSpecifiedNonce() == true &&
384
1.58k
                !IsSpecialCurve(op.curveType.Get()) &&
385
1.58k
                op.nonce.ToTrimmedString() == "0"
386
1.58k
           ) {
387
0
            std::cout << "0 is an invalid ECDSA nonce" << std::endl;
388
0
            ::abort();
389
0
        }
390
391
1.58k
        test_ECDSA_Signature(op.curveType.Get(),
392
1.58k
                result->signature.first.ToTrimmedString(),
393
1.58k
                result->signature.second.ToTrimmedString());
394
1.58k
    }
395
3.40k
}
396
397
968
void test(const operation::ECGDSA_Sign& op, const std::optional<component::ECGDSA_Signature>& result) {
398
968
    if ( result != std::nullopt ) {
399
133
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
400
401
133
        if (
402
133
                op.UseSpecifiedNonce() == true &&
403
133
                !IsSpecialCurve(op.curveType.Get()) &&
404
133
                op.nonce.ToTrimmedString() == "0"
405
133
           ) {
406
0
            std::cout << "0 is an invalid ECGDSA nonce" << std::endl;
407
0
            ::abort();
408
0
        }
409
410
133
        test_ECDSA_Signature(op.curveType.Get(),
411
133
                result->signature.first.ToTrimmedString(),
412
133
                result->signature.second.ToTrimmedString());
413
133
    }
414
968
}
415
416
307
void test(const operation::ECRDSA_Sign& op, const std::optional<component::ECRDSA_Signature>& result) {
417
307
    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
307
}
434
435
292
void test(const operation::Schnorr_Sign& op, const std::optional<component::Schnorr_Signature>& result) {
436
292
    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
292
}
453
454
257
void test(const operation::ECCSI_Verify& op, const std::optional<bool>& result) {
455
257
    (void)op;
456
257
    (void)result;
457
257
}
458
459
1.64k
void test(const operation::ECDSA_Verify& op, const std::optional<bool>& result) {
460
1.64k
    if ( result != std::nullopt && *result == true ) {
461
45
        test_ECDSA_Signature(op.curveType.Get(),
462
45
                op.signature.signature.first.ToTrimmedString(),
463
45
                op.signature.signature.second.ToTrimmedString());
464
45
    }
465
1.64k
}
466
467
760
void test(const operation::ECGDSA_Verify& op, const std::optional<bool>& result) {
468
760
    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
760
}
474
475
220
void test(const operation::ECRDSA_Verify& op, const std::optional<bool>& result) {
476
220
    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
220
}
482
483
251
void test(const operation::Schnorr_Verify& op, const std::optional<bool>& result) {
484
251
    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
251
}
490
491
2.57k
void test(const operation::ECDSA_Recover& op, const std::optional<component::ECC_PublicKey>& result) {
492
2.57k
    if ( result != std::nullopt ) {
493
1.00k
        if ( op.id > 3 ) {
494
0
            std::cout << "Invalid recovery ID" << std::endl;
495
0
            ::abort();
496
0
        }
497
1.00k
    }
498
2.57k
    if ( result != std::nullopt ) {
499
1.00k
        test_ECDSA_Signature(op.curveType.Get(),
500
1.00k
                op.signature.first.ToTrimmedString(),
501
1.00k
                op.signature.second.ToTrimmedString());
502
1.00k
    }
503
2.57k
}
504
505
324
void test(const operation::DSA_Verify& op, const std::optional<bool>& result) {
506
324
    (void)op;
507
508
324
    if ( result == std::nullopt || *result == false ) {
509
324
        return;
510
324
    }
511
512
0
    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
0
    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
0
    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
0
    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
0
}
532
533
360
void test(const operation::DSA_Sign& op, const std::optional<component::DSA_Signature>& result) {
534
360
    if ( result == std::nullopt ) {
535
360
        return;
536
360
    }
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
238
void test(const operation::DSA_GenerateParameters& op, const std::optional<component::DSA_Parameters>& result) {
588
238
    (void)op;
589
590
238
    if ( result == std::nullopt ) {
591
238
        return;
592
238
    }
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
235
void test(const operation::DSA_PrivateToPublic& op, const std::optional<component::Bignum>& result) {
639
235
    (void)op;
640
235
    (void)result;
641
235
}
642
643
322
void test(const operation::DSA_GenerateKeyPair& op, const std::optional<component::DSA_KeyPair>& result) {
644
322
    if ( result == std::nullopt ) {
645
322
        return;
646
322
    }
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
266
void test(const operation::ECDH_Derive& op, const std::optional<component::Secret>& result) {
661
266
    (void)op;
662
266
    (void)result;
663
266
}
664
665
218
void test(const operation::ECIES_Encrypt& op, const std::optional<component::Ciphertext>& result) {
666
    /* TODO check minimum size? */
667
218
    (void)op;
668
218
    (void)result;
669
218
}
670
671
271
void test(const operation::ECIES_Decrypt& op, const std::optional<component::Cleartext>& result) {
672
271
    (void)op;
673
271
    (void)result;
674
271
}
675
676
504
void test(const operation::ECC_Point_Add& op, const std::optional<component::ECC_Point>& result) {
677
504
    (void)op;
678
504
    (void)result;
679
504
}
680
681
2.80k
void test(const operation::ECC_Point_Mul& op, const std::optional<component::ECC_Point>& result) {
682
2.80k
    (void)op;
683
2.80k
    (void)result;
684
2.80k
}
685
686
462
void test(const operation::ECC_Point_Neg& op, const std::optional<component::ECC_Point>& result) {
687
462
    (void)op;
688
462
    (void)result;
689
462
}
690
691
419
void test(const operation::ECC_Point_Dbl& op, const std::optional<component::ECC_Point>& result) {
692
419
    (void)op;
693
419
    (void)result;
694
419
}
695
696
538
void test(const operation::ECC_Point_Cmp& op, const std::optional<bool>& result) {
697
538
    (void)op;
698
538
    (void)result;
699
538
}
700
701
289
void test(const operation::DH_GenerateKeyPair& op, const std::optional<component::DH_KeyPair>& result) {
702
289
    (void)op;
703
289
    (void)result;
704
289
}
705
706
1.20k
void test(const operation::DH_Derive& op, const std::optional<component::Bignum>& result) {
707
1.20k
    (void)op;
708
1.20k
    (void)result;
709
1.20k
}
710
711
303
void test(const operation::BLS_PrivateToPublic& op, const std::optional<component::BLS_PublicKey>& result) {
712
303
    (void)op;
713
303
    (void)result;
714
303
}
715
716
275
void test(const operation::BLS_PrivateToPublic_G2& op, const std::optional<component::G2>& result) {
717
275
    (void)op;
718
275
    (void)result;
719
275
}
720
721
253
void test(const operation::BLS_Sign& op, const std::optional<component::BLS_Signature>& result) {
722
253
    (void)op;
723
253
    (void)result;
724
253
}
725
726
290
void test(const operation::BLS_Verify& op, const std::optional<bool>& result) {
727
290
    (void)op;
728
290
    (void)result;
729
290
}
730
731
302
void test(const operation::BLS_BatchSign& op, const std::optional<component::BLS_BatchSignature>& result) {
732
302
    (void)op;
733
302
    (void)result;
734
302
}
735
736
285
void test(const operation::BLS_BatchVerify& op, const std::optional<bool>& result) {
737
285
    (void)op;
738
285
    (void)result;
739
285
}
740
741
266
void test(const operation::BLS_Aggregate_G1& op, const std::optional<component::G1>& result) {
742
266
    (void)op;
743
266
    (void)result;
744
266
}
745
746
238
void test(const operation::BLS_Aggregate_G2& op, const std::optional<component::G2>& result) {
747
238
    (void)op;
748
238
    (void)result;
749
238
}
750
751
209
void test(const operation::BLS_Pairing& op, const std::optional<component::Fp12>& result) {
752
209
    (void)op;
753
209
    (void)result;
754
209
}
755
756
224
void test(const operation::BLS_MillerLoop& op, const std::optional<component::Fp12>& result) {
757
224
    (void)op;
758
224
    (void)result;
759
224
}
760
761
314
void test(const operation::BLS_FinalExp& op, const std::optional<component::Fp12>& result) {
762
314
    (void)op;
763
314
    (void)result;
764
314
}
765
766
256
void test(const operation::BLS_HashToG1& op, const std::optional<component::G1>& result) {
767
256
    (void)op;
768
256
    (void)result;
769
256
}
770
771
247
void test(const operation::BLS_HashToG2& op, const std::optional<component::G2>& result) {
772
247
    (void)op;
773
247
    (void)result;
774
247
}
775
776
306
void test(const operation::BLS_MapToG1& op, const std::optional<component::G1>& result) {
777
306
    (void)op;
778
306
    (void)result;
779
306
}
780
781
248
void test(const operation::BLS_MapToG2& op, const std::optional<component::G2>& result) {
782
248
    (void)op;
783
248
    (void)result;
784
248
}
785
786
247
void test(const operation::BLS_IsG1OnCurve& op, const std::optional<bool>& result) {
787
247
    (void)op;
788
247
    (void)result;
789
247
}
790
791
307
void test(const operation::BLS_IsG2OnCurve& op, const std::optional<bool>& result) {
792
307
    (void)op;
793
307
    (void)result;
794
307
}
795
796
284
void test(const operation::BLS_GenerateKeyPair& op, const std::optional<component::BLS_KeyPair>& result) {
797
284
    (void)op;
798
284
    (void)result;
799
284
}
800
801
227
void test(const operation::BLS_Decompress_G1& op, const std::optional<component::G1>& result) {
802
227
    (void)op;
803
227
    (void)result;
804
227
}
805
806
240
void test(const operation::BLS_Compress_G1& op, const std::optional<component::Bignum>& result) {
807
240
    (void)op;
808
240
    (void)result;
809
240
}
810
811
225
void test(const operation::BLS_Decompress_G2& op, const std::optional<component::G2>& result) {
812
225
    (void)op;
813
225
    (void)result;
814
225
}
815
816
258
void test(const operation::BLS_Compress_G2& op, const std::optional<component::G1>& result) {
817
258
    (void)op;
818
258
    (void)result;
819
258
}
820
821
328
void test(const operation::BLS_G1_Add& op, const std::optional<component::G1>& result) {
822
328
    (void)op;
823
328
    (void)result;
824
328
}
825
826
258
void test(const operation::BLS_G1_Mul& op, const std::optional<component::G1>& result) {
827
258
    (void)op;
828
258
    (void)result;
829
258
}
830
831
322
void test(const operation::BLS_G1_IsEq& op, const std::optional<bool>& result) {
832
322
    (void)op;
833
322
    (void)result;
834
322
}
835
836
281
void test(const operation::BLS_G1_Neg& op, const std::optional<component::G1>& result) {
837
281
    (void)op;
838
281
    (void)result;
839
281
}
840
841
450
void test(const operation::BLS_G2_Add& op, const std::optional<component::G2>& result) {
842
450
    (void)op;
843
450
    (void)result;
844
450
}
845
846
362
void test(const operation::BLS_G2_Mul& op, const std::optional<component::G2>& result) {
847
362
    (void)op;
848
362
    (void)result;
849
362
}
850
851
398
void test(const operation::BLS_G2_IsEq& op, const std::optional<bool>& result) {
852
398
    (void)op;
853
398
    (void)result;
854
398
}
855
856
357
void test(const operation::BLS_G2_Neg& op, const std::optional<component::G2>& result) {
857
357
    (void)op;
858
357
    (void)result;
859
357
}
860
861
222
void test(const operation::Misc& op, const std::optional<Buffer>& result) {
862
222
    (void)op;
863
222
    (void)result;
864
222
}
865
866
239
void test(const operation::SR25519_Verify& op, const std::optional<bool>& result) {
867
239
    (void)op;
868
239
    (void)result;
869
239
}
870
871
namespace BignumCalc {
872
0
    static void Abort(const std::string& message, const std::string& opStr) {
873
0
        std::cout << "BignumCalc ( " << opStr << " ): " << message << std::endl;
874
0
        ::abort();
875
0
    }
876
678
    static void AssertBinary(const component::Bignum& result, const std::string& opStr) {
877
678
        const auto resultStr = result.ToTrimmedString();
878
678
        if ( !(resultStr == "0" || resultStr == "1") ) {
879
0
            Abort("Result must be 0 or 1", opStr);
880
0
        }
881
678
    }
882
209
    static void AssertTertiary(const component::Bignum& result, const std::string& opStr) {
883
209
        const auto resultStr = result.ToTrimmedString();
884
209
        if ( !(resultStr == "0" || resultStr == "1" || resultStr == "-1") ) {
885
0
            Abort("Result must be 0 or 1 or -1", opStr);
886
0
        }
887
209
    }
888
0
    static bool IsEqual(const component::Bignum& A, const component::Bignum& B) {
889
0
        return A.ToTrimmedString() == B.ToTrimmedString();
890
0
    }
891
1.07k
    static bool IsZero(const component::Bignum& A) {
892
1.07k
        return A.ToTrimmedString() == "0";
893
1.07k
    }
894
653
    static bool SmallerThan(const component::Bignum& A, const component::Bignum& B) {
895
653
        return A.ToTrimmedString().size() < B.ToTrimmedString().size();
896
653
    }
897
1.02k
    static bool LargerThan(const component::Bignum& A, const component::Bignum& B) {
898
1.02k
        return A.ToTrimmedString().size() > B.ToTrimmedString().size();
899
1.02k
    }
900
1.46k
    static bool IsEqualOrLargerThan(const component::Bignum& A, const component::Bignum& B) {
901
1.46k
        const auto a = A.ToTrimmedString();
902
1.46k
        const auto b = B.ToTrimmedString();
903
1.46k
        if ( a.size() > b.size() ) {
904
0
            return true;
905
0
        }
906
1.46k
        if ( a.size() == b.size() ) {
907
1.01k
            if ( a == b ) {
908
0
                return true;
909
0
            }
910
1.01k
        }
911
1.46k
        return false;
912
1.46k
    }
913
1.46k
    static void AssertModResult(const component::Bignum& result, const component::Bignum& mod, const std::string& opStr) {
914
1.46k
        if ( IsEqualOrLargerThan(result, mod) ) {
915
0
            Abort("Result is equal to or larger than modulo", opStr);
916
0
        }
917
1.46k
    }
918
264
    static void AssertNotSmallerThan(const component::Bignum& result, const component::Bignum& A, const std::string& opStr) {
919
264
        if ( SmallerThan(result, A) ) {
920
0
            Abort("Result is smaller than the input", opStr);
921
0
        }
922
264
    }
923
    static void AssertNotSmallerThan(
924
            const component::Bignum& result,
925
            const component::Bignum& A,
926
            const component::Bignum& B,
927
281
            const std::string& opStr) {
928
281
        if ( SmallerThan(result, A) && SmallerThan(result, B) ) {
929
0
            Abort("Result is smaller than the input", opStr);
930
0
        }
931
281
    }
932
506
    static void AssertNotLargerThan(const component::Bignum& result, const component::Bignum& A, const std::string& opStr) {
933
506
        if ( LargerThan(result, A) ) {
934
0
            Abort("Result is larger than the input", opStr);
935
0
        }
936
506
    }
937
    static void AssertNotLargerThan(
938
            const component::Bignum& result,
939
            const component::Bignum& A,
940
            const component::Bignum& B,
941
260
            const std::string& opStr) {
942
260
        if ( LargerThan(result, A) && LargerThan(result, B) ) {
943
0
            Abort("Result is larger than the input", opStr);
944
0
        }
945
260
    }
946
}
947
948
29.9k
void test(const operation::BignumCalc& op, const std::optional<component::Bignum>& result) {
949
29.9k
    if ( result == std::nullopt ) {
950
22.2k
        return;
951
22.2k
    }
952
953
7.72k
    using namespace BignumCalc;
954
955
7.72k
    const auto calcOp = op.calcOp.Get();
956
957
    /* Negative numbers are not supported yet */
958
7.72k
    if (    op.bn0.IsNegative() ||
959
7.72k
            op.bn1.IsNegative() ||
960
7.72k
            op.bn2.IsNegative() ) {
961
0
        return;
962
0
    }
963
964
    /* Modular calculations are not supported yet */
965
7.72k
    if ( op.modulo != std::nullopt ) {
966
1.42k
        return;
967
1.42k
    }
968
969
6.29k
    switch ( calcOp ) {
970
44
        case    CF_CALCOP("Add(A,B)"):
971
44
            if (    SmallerThan(*result, op.bn0) ||
972
44
                    SmallerThan(*result, op.bn1) ) {
973
0
                Abort("Result is smaller than its operands", repository::CalcOpToString(calcOp));
974
0
            }
975
44
            break;
976
236
        case    CF_CALCOP("Div(A,B)"):
977
236
            if ( IsZero(op.bn1) ) {
978
0
                Abort("Division by zero should not produce a result", repository::CalcOpToString(calcOp));
979
0
            }
980
981
236
            if ( LargerThan(*result, op.bn0) ) {
982
0
                Abort("Result is larger than the dividend", repository::CalcOpToString(calcOp));
983
0
            }
984
236
            break;
985
67
        case    CF_CALCOP("Mul(A,B)"):
986
67
            if ( IsZero(op.bn0) || IsZero(op.bn1) ) {
987
43
                if ( !IsZero(*result) ) {
988
0
                    Abort("Result of Mul with zero operand is not zero", repository::CalcOpToString(calcOp));
989
0
                }
990
43
            }
991
67
            break;
992
223
        case    CF_CALCOP("Mod(A,B)"):
993
223
            BignumCalc::AssertModResult(*result, op.bn1, "Mod");
994
223
            break;
995
823
        case    CF_CALCOP("ExpMod(A,B,C)"):
996
823
            BignumCalc::AssertModResult(*result, op.bn2, "ExpMod");
997
823
            break;
998
97
        case    CF_CALCOP("AddMod(A,B,C)"):
999
97
            BignumCalc::AssertModResult(*result, op.bn2, "AddMod");
1000
97
            break;
1001
128
        case    CF_CALCOP("SubMod(A,B,C)"):
1002
128
            BignumCalc::AssertModResult(*result, op.bn2, "SubMod");
1003
128
            break;
1004
96
        case    CF_CALCOP("MulMod(A,B,C)"):
1005
96
            BignumCalc::AssertModResult(*result, op.bn2, "MulMod");
1006
96
            break;
1007
96
        case    CF_CALCOP("SqrMod(A,B)"):
1008
96
            BignumCalc::AssertModResult(*result, op.bn1, "SqrMod");
1009
96
            break;
1010
0
        case    CF_CALCOP("SqrtMod(A,B)"):
1011
0
            BignumCalc::AssertModResult(*result, op.bn1, "SqrtMod");
1012
0
            break;
1013
0
        case    CF_CALCOP("ModLShift(A,B,C)"):
1014
0
            BignumCalc::AssertModResult(*result, op.bn2, "ModLShift");
1015
0
            break;
1016
51
        case    CF_CALCOP("Bit(A,B)"):
1017
51
            BignumCalc::AssertBinary(*result, "Bit");
1018
51
            break;
1019
0
        case    CF_CALCOP("IsCoprime(A,B)"):
1020
0
            BignumCalc::AssertBinary(*result, "IsCoprime");
1021
0
            break;
1022
39
        case    CF_CALCOP("IsEq(A,B)"):
1023
39
            BignumCalc::AssertBinary(*result, "IsEq");
1024
39
            break;
1025
21
        case    CF_CALCOP("IsGt(A,B)"):
1026
21
            BignumCalc::AssertBinary(*result, "IsGt");
1027
21
            break;
1028
29
        case    CF_CALCOP("IsGte(A,B)"):
1029
29
            BignumCalc::AssertBinary(*result, "IsGte");
1030
29
            break;
1031
21
        case    CF_CALCOP("IsLt(A,B)"):
1032
21
            BignumCalc::AssertBinary(*result, "IsLt");
1033
21
            break;
1034
15
        case    CF_CALCOP("IsLte(A,B)"):
1035
15
            BignumCalc::AssertBinary(*result, "IsLte");
1036
15
            break;
1037
25
        case    CF_CALCOP("IsEven(A)"):
1038
25
            BignumCalc::AssertBinary(*result, "IsEven");
1039
25
            break;
1040
16
        case    CF_CALCOP("IsOdd(A)"):
1041
16
            BignumCalc::AssertBinary(*result, "IsOdd");
1042
16
            break;
1043
21
        case    CF_CALCOP("IsOne(A)"):
1044
21
            BignumCalc::AssertBinary(*result, "IsOne");
1045
21
            break;
1046
0
        case    CF_CALCOP("IsPow2(A)"):
1047
0
            BignumCalc::AssertBinary(*result, "IsPow2");
1048
0
            break;
1049
373
        case    CF_CALCOP("IsPrime(A)"):
1050
373
            BignumCalc::AssertBinary(*result, "IsPrime");
1051
373
            break;
1052
26
        case    CF_CALCOP("IsZero(A)"):
1053
26
            BignumCalc::AssertBinary(*result, "IsZero");
1054
26
            break;
1055
0
        case    CF_CALCOP("IsSquare(A)"):
1056
0
            BignumCalc::AssertBinary(*result, "IsSquare");
1057
0
            break;
1058
0
        case    CF_CALCOP("IsPower(A)"):
1059
0
            BignumCalc::AssertBinary(*result, "IsPower");
1060
0
            break;
1061
20
        case    CF_CALCOP("IsNeg(A)"):
1062
20
            BignumCalc::AssertBinary(*result, "IsNeg");
1063
20
            break;
1064
21
        case    CF_CALCOP("IsNotZero(A)"):
1065
21
            BignumCalc::AssertBinary(*result, "IsNotZero");
1066
21
            break;
1067
32
        case    CF_CALCOP("Cmp(A,B)"):
1068
32
            BignumCalc::AssertTertiary(*result, "Cmp");
1069
32
            break;
1070
81
        case    CF_CALCOP("CmpAbs(A,B)"):
1071
81
            BignumCalc::AssertTertiary(*result, "CmpAbs");
1072
81
            break;
1073
96
        case    CF_CALCOP("Jacobi(A,B)"):
1074
96
            BignumCalc::AssertTertiary(*result, "Jacobi");
1075
96
            break;
1076
59
        case    CF_CALCOP("Sqr(A)"):
1077
59
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1078
59
            break;
1079
166
        case    CF_CALCOP("RShift(A,B)"):
1080
166
            if ( IsZero(op.bn0) || IsZero(op.bn1) ) {
1081
143
                if ( op.bn0.ToTrimmedString() != result->ToTrimmedString() ) {
1082
0
                    Abort("Zero operand should not alter input", repository::CalcOpToString(calcOp));
1083
0
                }
1084
143
            }
1085
1086
166
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1087
166
            break;
1088
63
        case    CF_CALCOP("LShift1(A)"):
1089
63
            if ( IsZero(op.bn0) ) {
1090
43
                if ( op.bn0.ToTrimmedString() != result->ToTrimmedString() ) {
1091
0
                    Abort("Zero input should remain zero", repository::CalcOpToString(calcOp));
1092
0
                }
1093
43
            }
1094
1095
63
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1096
63
            break;
1097
81
        case    CF_CALCOP("SetBit(A,B)"):
1098
81
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1099
81
            break;
1100
68
        case    CF_CALCOP("ClearBit(A,B)"):
1101
68
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1102
68
            break;
1103
46
        case    CF_CALCOP("Sqrt(A)"):
1104
46
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1105
46
            break;
1106
0
        case    CF_CALCOP("Cbrt(A)"):
1107
0
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1108
0
            break;
1109
61
        case    CF_CALCOP("MulAdd(A,B,C)"):
1110
61
            AssertNotSmallerThan(*result, op.bn2, repository::CalcOpToString(calcOp));
1111
61
            break;
1112
0
        case    CF_CALCOP("Min(A,B)"):
1113
0
        case    CF_CALCOP("Max(A,B)"):
1114
0
            if ( !IsEqual(*result, op.bn0) && !IsEqual(*result, op.bn1) ) {
1115
0
                Abort("Result is not an operand", repository::CalcOpToString(calcOp));
1116
0
            }
1117
0
            break;
1118
0
        case    CF_CALCOP("Mask(A,B)"):
1119
0
            if ( LargerThan(*result, op.bn0) ) {
1120
0
                Abort("Result is larger than input", repository::CalcOpToString(calcOp));
1121
0
            }
1122
0
            break;
1123
0
        case    CF_CALCOP("And(A,B)"):
1124
0
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1125
0
            AssertNotLargerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1126
0
            break;
1127
0
        case    CF_CALCOP("Or(A,B)"):
1128
0
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
1129
0
            AssertNotSmallerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1130
0
            break;
1131
0
        case    CF_CALCOP("Nthrt(A,B)"):
1132
0
        case    CF_CALCOP("NthrtRem(A,B)"):
1133
0
            if ( IsZero(op.bn1) ) {
1134
0
                Abort("Root of zero should not produce a result", repository::CalcOpToString(calcOp));
1135
0
            }
1136
0
            break;
1137
0
        case    CF_CALCOP("Zero()"):
1138
0
            if ( !IsZero(*result) ) {
1139
0
                Abort("Result should be zero", repository::CalcOpToString(calcOp));
1140
0
            }
1141
0
            break;
1142
260
        case    CF_CALCOP("GCD(A,B)"):
1143
260
            AssertNotLargerThan(*result, op.bn0, op.bn1, repository::CalcOpToString(calcOp));
1144
260
            break;
1145
281
        case    CF_CALCOP("LCM(A,B)"):
1146
281
            AssertNotSmallerThan(*result, op.bn0, op.bn1, repository::CalcOpToString(calcOp));
1147
281
            break;
1148
357
        case    CF_CALCOP("InvMod(A,B)"):
1149
357
            if ( !IsZero(*result) ) {
1150
226
                AssertNotLargerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
1151
226
            }
1152
357
            break;
1153
0
        case    CF_CALCOP("Exp(A,B)"):
1154
0
            AssertNotSmallerThan(*result, op.bn0, op.bn1, repository::CalcOpToString(calcOp));
1155
0
            break;
1156
6.29k
    }
1157
6.29k
}
1158
1159
415
void test(const operation::BignumCalc_Fp2& op, const std::optional<component::Fp2>& result) {
1160
415
    (void)op;
1161
415
    (void)result;
1162
415
}
1163
1164
1.36k
void test(const operation::BignumCalc_Fp12& op, const std::optional<component::Fp12>& result) {
1165
1.36k
    (void)op;
1166
1.36k
    (void)result;
1167
1.36k
}
1168
1169
} /* namespace tests */
1170
} /* namespace cryptofuzz */