Coverage Report

Created: 2022-08-24 06:37

/src/cryptofuzz-sp-math-all-8bit/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
1.53k
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
1.53k
    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.53k
}
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
154
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
154
    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
154
}
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
190
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
190
    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
190
}
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
175
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
175
    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
175
}
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
161
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
161
    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
161
}
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
220
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
220
    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
220
}
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
95
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
95
    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
95
}
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
40
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
40
    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
40
}
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
112
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
112
    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
112
}
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
209
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
209
    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
209
}
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
7
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
7
    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
7
}
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
169
void verifyKeySize(const OperationType& op, const ResultType& result) {
13
169
    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
169
}
18
19
778
void test(const operation::Digest& op, const std::optional<component::Digest>& result) {
20
778
    if ( result == std::nullopt ) {
21
236
        return;
22
236
    }
23
24
542
    const auto expectedSize = repository::DigestSize(op.digestType.Get());
25
26
542
    if ( expectedSize == std::nullopt ) {
27
0
        return;
28
0
    }
29
30
542
    if ( result->GetSize() != *expectedSize ) {
31
0
        printf("Expected vs actual digest size: %zu / %zu\n", *expectedSize, result->GetSize());
32
0
        abort();
33
0
    }
34
542
}
35
36
643
void test(const operation::HMAC& op, const std::optional<component::MAC>& result) {
37
643
    if ( result == std::nullopt ) {
38
288
        return;
39
288
    }
40
41
355
    const auto expectedSize = repository::DigestSize(op.digestType.Get());
42
43
355
    if ( expectedSize == std::nullopt ) {
44
0
        return;
45
0
    }
46
47
355
    if ( result->GetSize() != *expectedSize ) {
48
0
        printf("Expected vs actual digest size: %zu / %zu\n", *expectedSize, result->GetSize());
49
0
        abort();
50
0
    }
51
355
}
52
53
64
void test(const operation::UMAC& op, const std::optional<component::MAC>& result) {
54
64
    if ( result == std::nullopt ) {
55
64
        return;
56
64
    }
57
58
0
    if (
59
0
            ( op.type == 0 && result->GetSize() > (32/8) ) ||
60
0
            ( op.type == 1 && result->GetSize() > (64/8) ) ||
61
0
            ( op.type == 2 && result->GetSize() > (96/8) ) ||
62
0
            ( op.type == 3 && result->GetSize() > (128/8) )
63
0
    ) {
64
0
        printf("UMAC: Overlong result: %zu\n", result->GetSize());
65
0
        abort();
66
0
    }
67
0
}
68
69
791
static void test_ChaCha20_Poly1305_IV(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
70
791
    using fuzzing::datasource::ID;
71
72
    /*
73
     * OpenSSL CVE-2019-1543
74
     * https://www.openssl.org/news/secadv/20190306.txt
75
     */
76
77
791
    if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20_POLY1305") ) {
78
788
        return;
79
788
    }
80
81
3
    if ( result == std::nullopt ) {
82
3
        return;
83
3
    }
84
85
0
    if ( op.cipher.iv.GetSize() > 12 ) {
86
0
        abort();
87
0
    }
88
0
}
89
90
791
static void test_XChaCha20_Poly1305_IV(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
91
791
    using fuzzing::datasource::ID;
92
93
791
    if ( op.cipher.cipherType.Get() != CF_CIPHER("XCHACHA20_POLY1305") ) {
94
784
        return;
95
784
    }
96
97
7
    if ( result == std::nullopt ) {
98
7
        return;
99
7
    }
100
101
0
    if ( op.cipher.iv.GetSize() != 24 ) {
102
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());
103
0
        abort();
104
0
    }
105
0
}
106
107
791
static void test_AES_CCM_Wycheproof(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
108
791
    bool fail = false;
109
110
791
    if ( result == std::nullopt ) {
111
504
        return;
112
504
    }
113
114
287
    switch ( op.cipher.cipherType.Get() ) {
115
0
        case CF_CIPHER("AES_128_CCM"):
116
0
        case CF_CIPHER("AES_192_CCM"):
117
0
        case CF_CIPHER("AES_256_CCM"):
118
0
            break;
119
287
        default:
120
287
            return;
121
287
    }
122
123
0
    if ( op.cipher.iv.GetSize() < 7 || op.cipher.iv.GetSize() > 13 ) {
124
0
        printf("AES CCM: Invalid IV size\n");
125
0
        fail = true;
126
0
    }
127
128
0
    if ( result->tag != std::nullopt ) {
129
0
        static const std::vector<size_t> validTagSizes = {4, 6, 8, 10, 12, 14, 16};
130
131
0
        if ( std::find(validTagSizes.begin(), validTagSizes.end(), result->tag->GetSize()) == validTagSizes.end() ) {
132
0
            printf("AES CCM: Invalid tag size\n");
133
0
            fail = true;
134
0
        }
135
0
    }
136
137
0
    if ( fail == true ) {
138
0
        printf("AES CCM tests based on Wycheproof: https://github.com/google/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/aes_ccm_test.json#L11\n");
139
0
        abort();
140
0
    }
141
0
}
142
143
791
static void test_AES_GCM_Wycheproof(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
144
791
    bool fail = false;
145
146
791
    if ( result == std::nullopt ) {
147
504
        return;
148
504
    }
149
150
287
    switch ( op.cipher.cipherType.Get() ) {
151
1
        case CF_CIPHER("AES_128_GCM"):
152
1
        case CF_CIPHER("AES_192_GCM"):
153
14
        case CF_CIPHER("AES_256_GCM"):
154
14
            break;
155
273
        default:
156
273
            return;
157
287
    }
158
159
14
    if ( op.cipher.iv.GetSize() == 0 ) {
160
0
        printf("AES GCM: Invalid IV size\n");
161
0
        fail = true;
162
0
    }
163
164
14
    if ( fail == true ) {
165
0
        printf("AES GCM tests based on Wycheproof: https://github.com/google/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/aes_gcm_test.json#L13\n");
166
0
        abort();
167
0
    }
168
14
}
169
170
791
void test(const operation::SymmetricEncrypt& op, const std::optional<component::Ciphertext>& result) {
171
791
    test_ChaCha20_Poly1305_IV(op, result);
172
791
    test_XChaCha20_Poly1305_IV(op, result);
173
791
    test_AES_CCM_Wycheproof(op, result);
174
791
    test_AES_GCM_Wycheproof(op, result);
175
791
}
176
177
847
void test(const operation::SymmetricDecrypt& op, const std::optional<component::Cleartext>& result) {
178
847
    (void)op;
179
847
    (void)result;
180
847
}
181
182
97
void test(const operation::CMAC& op, const std::optional<component::MAC>& result) {
183
97
    (void)op;
184
97
    (void)result;
185
97
}
186
187
154
void test(const operation::KDF_SCRYPT& op, const std::optional<component::Key>& result) {
188
154
    verifyKeySize(op, result);
189
154
}
190
191
190
static void test_HKDF_OutputSize(const operation::KDF_HKDF& op, const std::optional<component::Key>& result) {
192
190
    if ( result == std::nullopt ) {
193
190
        return;
194
190
    }
195
196
0
    const auto expectedSize = repository::DigestSize(op.digestType.Get());
197
198
0
    if ( expectedSize == std::nullopt ) {
199
0
        return;
200
0
    }
201
202
0
    const size_t maxOutputSize = 255 * *expectedSize;
203
204
0
    if ( result->GetSize() > maxOutputSize ) {
205
0
        printf("The output size of HKDF (%zu) is more than 255 * the size of the hash digest (%zu)\n", result->GetSize(), maxOutputSize);
206
0
        abort();
207
0
    }
208
0
}
209
210
190
void test(const operation::KDF_HKDF& op, const std::optional<component::Key>& result) {
211
190
    verifyKeySize(op, result);
212
213
190
    test_HKDF_OutputSize(op, result);
214
190
}
215
216
175
void test(const operation::KDF_TLS1_PRF& op, const std::optional<component::Key>& result) {
217
175
    verifyKeySize(op, result);
218
175
}
219
220
161
void test(const operation::KDF_PBKDF& op, const std::optional<component::Key>& result) {
221
161
    verifyKeySize(op, result);
222
161
}
223
224
220
void test(const operation::KDF_PBKDF1& op, const std::optional<component::Key>& result) {
225
220
    verifyKeySize(op, result);
226
220
}
227
228
95
void test(const operation::KDF_PBKDF2& op, const std::optional<component::Key>& result) {
229
95
    verifyKeySize(op, result);
230
95
}
231
232
40
void test(const operation::KDF_ARGON2& op, const std::optional<component::Key>& result) {
233
40
    verifyKeySize(op, result);
234
40
}
235
236
112
void test(const operation::KDF_SSH& op, const std::optional<component::Key>& result) {
237
112
    verifyKeySize(op, result);
238
112
}
239
240
209
void test(const operation::KDF_X963& op, const std::optional<component::Key>& result) {
241
209
    verifyKeySize(op, result);
242
209
}
243
244
7
void test(const operation::KDF_BCRYPT& op, const std::optional<component::Key>& result) {
245
7
    verifyKeySize(op, result);
246
7
}
247
248
169
void test(const operation::KDF_SP_800_108& op, const std::optional<component::Key>& result) {
249
169
    verifyKeySize(op, result);
250
169
}
251
252
11.7k
static bool IsSpecialCurve(const uint64_t curveID) {
253
11.7k
    switch ( curveID ) {
254
2.30k
        case CF_ECC_CURVE("ed448"):
255
5.92k
        case CF_ECC_CURVE("ed25519"):
256
5.92k
        case CF_ECC_CURVE("x25519"):
257
5.92k
        case CF_ECC_CURVE("x448"):
258
5.92k
            return true;
259
5.83k
        default:
260
5.83k
            return false;
261
11.7k
    }
262
11.7k
}
263
264
20.1k
static void test_ECC_PrivateKey(const uint64_t curveID, const std::string priv) {
265
    /* Disabled until all modules comply by default */
266
20.1k
    return;
267
268
    /* Private key may be 0 with these curves */
269
0
    if ( IsSpecialCurve(curveID) ) {
270
0
        return;
271
0
    }
272
273
0
    if ( priv == "0" ) {
274
0
        std::cout << "0 is an invalid elliptic curve private key" << std::endl;
275
0
        ::abort();
276
0
    }
277
0
}
278
279
280
12.9k
void test(const operation::ECC_PrivateToPublic& op, const std::optional<component::ECC_PublicKey>& result) {
281
12.9k
    if ( result != std::nullopt ) {
282
5.77k
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
283
5.77k
    }
284
12.9k
}
285
286
12.9k
void test(const operation::ECC_ValidatePubkey& op, const std::optional<bool>& result) {
287
12.9k
    (void)op;
288
12.9k
    (void)result;
289
12.9k
}
290
291
14.8k
void test(const operation::ECC_GenerateKeyPair& op, const std::optional<component::ECC_KeyPair>& result) {
292
14.8k
    if ( result != std::nullopt ) {
293
6.24k
        test_ECC_PrivateKey(op.curveType.Get(), result->priv.ToTrimmedString());
294
6.24k
    }
295
14.8k
}
296
297
8.65k
static void test_ECDSA_Signature(const uint64_t curveID, const std::string R, const std::string S) {
298
8.65k
    if ( IsSpecialCurve(curveID) ) {
299
4.71k
        return;
300
4.71k
    }
301
302
3.94k
    const boost::multiprecision::cpp_int r(R), s(S);
303
304
3.94k
    if ( r < 1 ) {
305
0
        std::cout << "ECDSA signature invalid: R < 1" << std::endl;
306
0
        ::abort();
307
0
    }
308
3.94k
    if ( s < 1 ) {
309
0
        std::cout << "ECDSA signature invalid: S < 1" << std::endl;
310
0
        ::abort();
311
0
    }
312
313
3.94k
    const auto O = cryptofuzz::repository::ECC_CurveToOrder(curveID);
314
3.94k
    if ( O == std::nullopt ) {
315
5
        return;
316
5
    }
317
318
3.94k
    const boost::multiprecision::cpp_int o(*O);
319
320
3.94k
    if ( r >= o ) {
321
0
        std::cout << "ECDSA signature invalid: R >= order" << std::endl;
322
0
        ::abort();
323
0
    }
324
325
3.94k
    if ( s >= o ) {
326
0
        std::cout << "ECDSA signature invalid: S >= order" << std::endl;
327
0
        ::abort();
328
0
    }
329
3.94k
}
330
331
0
static void test_BIP340_Schnorr_Signature(const uint64_t curveID, const std::string R, const std::string S) {
332
0
    boost::multiprecision::cpp_int r(R);
333
0
    boost::multiprecision::cpp_int s(S);
334
0
    if ( r < 1 ) {
335
0
        std::cout << "BIP340 Schnorr signature invalid: R < 1" << std::endl;
336
0
        ::abort();
337
0
    }
338
0
    if ( s < 1 ) {
339
0
        std::cout << "BIP340 Schnorr signature invalid: S < 1" << std::endl;
340
0
        ::abort();
341
0
    }
342
343
0
    const auto prime = cryptofuzz::repository::ECC_CurveToPrime(curveID);
344
0
    if ( prime != std::nullopt ) {
345
0
        const boost::multiprecision::cpp_int p(*prime);
346
0
        CF_ASSERT(r < p, "BIP340 Schnorr signature R should be less than curve P");
347
0
    }
348
349
0
    const auto order = cryptofuzz::repository::ECC_CurveToOrder(curveID);
350
0
    if ( order != std::nullopt ) {
351
0
        const boost::multiprecision::cpp_int n(*order);
352
0
        CF_ASSERT(s < n, "BIP340 Schnorr signature S should be less than curve N");
353
0
    }
354
0
}
355
356
17.0k
void test(const operation::ECDSA_Sign& op, const std::optional<component::ECDSA_Signature>& result) {
357
17.0k
    if ( result != std::nullopt ) {
358
8.16k
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
359
360
8.16k
        if (
361
8.16k
                op.UseSpecifiedNonce() == true &&
362
8.16k
                !IsSpecialCurve(op.curveType.Get()) &&
363
8.16k
                op.nonce.ToTrimmedString() == "0"
364
8.16k
           ) {
365
0
            std::cout << "0 is an invalid ECDSA nonce" << std::endl;
366
0
            ::abort();
367
0
        }
368
369
8.16k
        test_ECDSA_Signature(op.curveType.Get(),
370
8.16k
                result->signature.first.ToTrimmedString(),
371
8.16k
                result->signature.second.ToTrimmedString());
372
8.16k
    }
373
17.0k
}
374
375
41
void test(const operation::ECGDSA_Sign& op, const std::optional<component::ECGDSA_Signature>& result) {
376
41
    if ( result != std::nullopt ) {
377
0
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
378
379
0
        if (
380
0
                op.UseSpecifiedNonce() == true &&
381
0
                !IsSpecialCurve(op.curveType.Get()) &&
382
0
                op.nonce.ToTrimmedString() == "0"
383
0
           ) {
384
0
            std::cout << "0 is an invalid ECGDSA nonce" << std::endl;
385
0
            ::abort();
386
0
        }
387
388
0
        test_ECDSA_Signature(op.curveType.Get(),
389
0
                result->signature.first.ToTrimmedString(),
390
0
                result->signature.second.ToTrimmedString());
391
0
    }
392
41
}
393
394
59
void test(const operation::ECRDSA_Sign& op, const std::optional<component::ECRDSA_Signature>& result) {
395
59
    if ( result != std::nullopt ) {
396
0
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
397
398
0
        if (
399
0
                op.UseSpecifiedNonce() == true &&
400
0
                !IsSpecialCurve(op.curveType.Get()) &&
401
0
                op.nonce.ToTrimmedString() == "0"
402
0
           ) {
403
0
            std::cout << "0 is an invalid ECRDSA nonce" << std::endl;
404
0
            ::abort();
405
0
        }
406
407
0
        test_ECDSA_Signature(op.curveType.Get(),
408
0
                result->signature.first.ToTrimmedString(),
409
0
                result->signature.second.ToTrimmedString());
410
0
    }
411
59
}
412
413
48
void test(const operation::Schnorr_Sign& op, const std::optional<component::Schnorr_Signature>& result) {
414
48
    if ( result != std::nullopt ) {
415
0
        test_ECC_PrivateKey(op.curveType.Get(), op.priv.ToTrimmedString());
416
417
0
        if (
418
0
                op.UseSpecifiedNonce() == true &&
419
0
                !IsSpecialCurve(op.curveType.Get()) &&
420
0
                op.nonce.ToTrimmedString() == "0"
421
0
           ) {
422
0
            std::cout << "0 is an invalid Schnorr nonce" << std::endl;
423
0
            ::abort();
424
0
        }
425
426
0
        test_BIP340_Schnorr_Signature(op.curveType.Get(),
427
0
                result->signature.first.ToTrimmedString(),
428
0
                result->signature.second.ToTrimmedString());
429
0
    }
430
48
}
431
432
10.6k
void test(const operation::ECDSA_Verify& op, const std::optional<bool>& result) {
433
10.6k
    if ( result != std::nullopt && *result == true ) {
434
489
        test_ECDSA_Signature(op.curveType.Get(),
435
489
                op.signature.signature.first.ToTrimmedString(),
436
489
                op.signature.signature.second.ToTrimmedString());
437
489
    }
438
10.6k
}
439
440
44
void test(const operation::ECGDSA_Verify& op, const std::optional<bool>& result) {
441
44
    if ( result != std::nullopt && *result == true ) {
442
0
        test_ECDSA_Signature(op.curveType.Get(),
443
0
                op.signature.signature.first.ToTrimmedString(),
444
0
                op.signature.signature.second.ToTrimmedString());
445
0
    }
446
44
}
447
448
37
void test(const operation::ECRDSA_Verify& op, const std::optional<bool>& result) {
449
37
    if ( result != std::nullopt && *result == true ) {
450
0
        test_ECDSA_Signature(op.curveType.Get(),
451
0
                op.signature.signature.first.ToTrimmedString(),
452
0
                op.signature.signature.second.ToTrimmedString());
453
0
    }
454
37
}
455
456
31
void test(const operation::Schnorr_Verify& op, const std::optional<bool>& result) {
457
31
    if ( result != std::nullopt && *result == true ) {
458
0
        test_BIP340_Schnorr_Signature(op.curveType.Get(),
459
0
                op.signature.signature.first.ToTrimmedString(),
460
0
                op.signature.signature.second.ToTrimmedString());
461
0
    }
462
31
}
463
464
47
void test(const operation::ECDSA_Recover& op, const std::optional<component::ECC_PublicKey>& result) {
465
47
    if ( result != std::nullopt ) {
466
0
        if ( op.id > 3 ) {
467
0
            std::cout << "Invalid recovery ID" << std::endl;
468
0
            ::abort();
469
0
        }
470
0
    }
471
47
    if ( result != std::nullopt ) {
472
0
        test_ECDSA_Signature(op.curveType.Get(),
473
0
                op.signature.first.ToTrimmedString(),
474
0
                op.signature.second.ToTrimmedString());
475
0
    }
476
47
}
477
478
1.67k
void test(const operation::ECDH_Derive& op, const std::optional<component::Secret>& result) {
479
1.67k
    (void)op;
480
1.67k
    (void)result;
481
1.67k
}
482
483
2.86k
void test(const operation::ECIES_Encrypt& op, const std::optional<component::Ciphertext>& result) {
484
    /* TODO check minimum size? */
485
2.86k
    (void)op;
486
2.86k
    (void)result;
487
2.86k
}
488
489
2.28k
void test(const operation::ECIES_Decrypt& op, const std::optional<component::Cleartext>& result) {
490
2.28k
    (void)op;
491
2.28k
    (void)result;
492
2.28k
}
493
494
5.03k
void test(const operation::ECC_Point_Add& op, const std::optional<component::ECC_Point>& result) {
495
5.03k
    (void)op;
496
5.03k
    (void)result;
497
5.03k
}
498
499
8.45k
void test(const operation::ECC_Point_Mul& op, const std::optional<component::ECC_Point>& result) {
500
8.45k
    (void)op;
501
8.45k
    (void)result;
502
8.45k
}
503
504
31
void test(const operation::ECC_Point_Neg& op, const std::optional<component::ECC_Point>& result) {
505
31
    (void)op;
506
31
    (void)result;
507
31
}
508
509
49
void test(const operation::ECC_Point_Dbl& op, const std::optional<component::ECC_Point>& result) {
510
49
    (void)op;
511
49
    (void)result;
512
49
}
513
514
11.4k
void test(const operation::DH_GenerateKeyPair& op, const std::optional<component::DH_KeyPair>& result) {
515
11.4k
    (void)op;
516
11.4k
    (void)result;
517
11.4k
}
518
519
5.33k
void test(const operation::DH_Derive& op, const std::optional<component::Bignum>& result) {
520
5.33k
    (void)op;
521
5.33k
    (void)result;
522
5.33k
}
523
524
76
void test(const operation::BLS_PrivateToPublic& op, const std::optional<component::BLS_PublicKey>& result) {
525
76
    (void)op;
526
76
    (void)result;
527
76
}
528
529
54
void test(const operation::BLS_PrivateToPublic_G2& op, const std::optional<component::G2>& result) {
530
54
    (void)op;
531
54
    (void)result;
532
54
}
533
534
61
void test(const operation::BLS_Sign& op, const std::optional<component::BLS_Signature>& result) {
535
61
    (void)op;
536
61
    (void)result;
537
61
}
538
539
40
void test(const operation::BLS_Verify& op, const std::optional<bool>& result) {
540
40
    (void)op;
541
40
    (void)result;
542
40
}
543
544
48
void test(const operation::BLS_BatchSign& op, const std::optional<component::BLS_BatchSignature>& result) {
545
48
    (void)op;
546
48
    (void)result;
547
48
}
548
549
16
void test(const operation::BLS_BatchVerify& op, const std::optional<bool>& result) {
550
16
    (void)op;
551
16
    (void)result;
552
16
}
553
554
40
void test(const operation::BLS_Aggregate_G1& op, const std::optional<component::G1>& result) {
555
40
    (void)op;
556
40
    (void)result;
557
40
}
558
559
50
void test(const operation::BLS_Aggregate_G2& op, const std::optional<component::G2>& result) {
560
50
    (void)op;
561
50
    (void)result;
562
50
}
563
564
43
void test(const operation::BLS_Pairing& op, const std::optional<component::Fp12>& result) {
565
43
    (void)op;
566
43
    (void)result;
567
43
}
568
569
47
void test(const operation::BLS_MillerLoop& op, const std::optional<component::Fp12>& result) {
570
47
    (void)op;
571
47
    (void)result;
572
47
}
573
574
47
void test(const operation::BLS_FinalExp& op, const std::optional<component::Fp12>& result) {
575
47
    (void)op;
576
47
    (void)result;
577
47
}
578
579
52
void test(const operation::BLS_HashToG1& op, const std::optional<component::G1>& result) {
580
52
    (void)op;
581
52
    (void)result;
582
52
}
583
584
55
void test(const operation::BLS_HashToG2& op, const std::optional<component::G2>& result) {
585
55
    (void)op;
586
55
    (void)result;
587
55
}
588
589
43
void test(const operation::BLS_MapToG1& op, const std::optional<component::G1>& result) {
590
43
    (void)op;
591
43
    (void)result;
592
43
}
593
594
30
void test(const operation::BLS_MapToG2& op, const std::optional<component::G2>& result) {
595
30
    (void)op;
596
30
    (void)result;
597
30
}
598
599
60
void test(const operation::BLS_IsG1OnCurve& op, const std::optional<bool>& result) {
600
60
    (void)op;
601
60
    (void)result;
602
60
}
603
604
83
void test(const operation::BLS_IsG2OnCurve& op, const std::optional<bool>& result) {
605
83
    (void)op;
606
83
    (void)result;
607
83
}
608
609
26
void test(const operation::BLS_GenerateKeyPair& op, const std::optional<component::BLS_KeyPair>& result) {
610
26
    (void)op;
611
26
    (void)result;
612
26
}
613
614
34
void test(const operation::BLS_Decompress_G1& op, const std::optional<component::G1>& result) {
615
34
    (void)op;
616
34
    (void)result;
617
34
}
618
619
38
void test(const operation::BLS_Compress_G1& op, const std::optional<component::Bignum>& result) {
620
38
    (void)op;
621
38
    (void)result;
622
38
}
623
624
41
void test(const operation::BLS_Decompress_G2& op, const std::optional<component::G2>& result) {
625
41
    (void)op;
626
41
    (void)result;
627
41
}
628
629
32
void test(const operation::BLS_Compress_G2& op, const std::optional<component::G1>& result) {
630
32
    (void)op;
631
32
    (void)result;
632
32
}
633
634
84
void test(const operation::BLS_G1_Add& op, const std::optional<component::G1>& result) {
635
84
    (void)op;
636
84
    (void)result;
637
84
}
638
639
76
void test(const operation::BLS_G1_Mul& op, const std::optional<component::G1>& result) {
640
76
    (void)op;
641
76
    (void)result;
642
76
}
643
644
97
void test(const operation::BLS_G1_IsEq& op, const std::optional<bool>& result) {
645
97
    (void)op;
646
97
    (void)result;
647
97
}
648
649
58
void test(const operation::BLS_G1_Neg& op, const std::optional<component::G1>& result) {
650
58
    (void)op;
651
58
    (void)result;
652
58
}
653
654
95
void test(const operation::BLS_G2_Add& op, const std::optional<component::G2>& result) {
655
95
    (void)op;
656
95
    (void)result;
657
95
}
658
659
71
void test(const operation::BLS_G2_Mul& op, const std::optional<component::G2>& result) {
660
71
    (void)op;
661
71
    (void)result;
662
71
}
663
664
86
void test(const operation::BLS_G2_IsEq& op, const std::optional<bool>& result) {
665
86
    (void)op;
666
86
    (void)result;
667
86
}
668
669
69
void test(const operation::BLS_G2_Neg& op, const std::optional<component::G2>& result) {
670
69
    (void)op;
671
69
    (void)result;
672
69
}
673
674
44
void test(const operation::Misc& op, const std::optional<Buffer>& result) {
675
44
    (void)op;
676
44
    (void)result;
677
44
}
678
679
57
void test(const operation::SR25519_Verify& op, const std::optional<bool>& result) {
680
57
    (void)op;
681
57
    (void)result;
682
57
}
683
684
namespace BignumCalc {
685
0
    static void Abort(const std::string& message, const std::string& opStr) {
686
0
        std::cout << "BignumCalc ( " << opStr << " ): " << message << std::endl;
687
0
        ::abort();
688
0
    }
689
2.72k
    static void AssertBinary(const component::Bignum& result, const std::string& opStr) {
690
2.72k
        const auto resultStr = result.ToTrimmedString();
691
2.72k
        if ( !(resultStr == "0" || resultStr == "1") ) {
692
0
            Abort("Result must be 0 or 1", opStr);
693
0
        }
694
2.72k
    }
695
2.48k
    static void AssertTertiary(const component::Bignum& result, const std::string& opStr) {
696
2.48k
        const auto resultStr = result.ToTrimmedString();
697
2.48k
        if ( !(resultStr == "0" || resultStr == "1" || resultStr == "-1") ) {
698
0
            Abort("Result must be 0 or 1 or -1", opStr);
699
0
        }
700
2.48k
    }
701
0
    static bool IsEqual(const component::Bignum& A, const component::Bignum& B) {
702
0
        return A.ToTrimmedString() == B.ToTrimmedString();
703
0
    }
704
7.86k
    static bool IsZero(const component::Bignum& A) {
705
7.86k
        return A.ToTrimmedString() == "0";
706
7.86k
    }
707
5.34k
    static bool SmallerThan(const component::Bignum& A, const component::Bignum& B) {
708
5.34k
        return A.ToTrimmedString().size() < B.ToTrimmedString().size();
709
5.34k
    }
710
3.68k
    static bool LargerThan(const component::Bignum& A, const component::Bignum& B) {
711
3.68k
        return A.ToTrimmedString().size() > B.ToTrimmedString().size();
712
3.68k
    }
713
12.3k
    static bool IsEqualOrLargerThan(const component::Bignum& A, const component::Bignum& B) {
714
12.3k
        const auto a = A.ToTrimmedString();
715
12.3k
        const auto b = B.ToTrimmedString();
716
12.3k
        if ( a.size() > b.size() ) {
717
0
            return true;
718
0
        }
719
12.3k
        if ( a.size() == b.size() ) {
720
8.13k
            if ( a == b ) {
721
0
                return true;
722
0
            }
723
8.13k
        }
724
12.3k
        return false;
725
12.3k
    }
726
12.3k
    static void AssertModResult(const component::Bignum& result, const component::Bignum& mod, const std::string& opStr) {
727
12.3k
        if ( IsEqualOrLargerThan(result, mod) ) {
728
0
            Abort("Result is equal to or larger than modulo", opStr);
729
0
        }
730
12.3k
    }
731
3.54k
    static void AssertNotSmallerThan(const component::Bignum& result, const component::Bignum& A, const std::string& opStr) {
732
3.54k
        if ( SmallerThan(result, A) ) {
733
0
            Abort("Result is larger than the input", opStr);
734
0
        }
735
3.54k
    }
736
2.96k
    static void AssertNotLargerThan(const component::Bignum& result, const component::Bignum& A, const std::string& opStr) {
737
2.96k
        if ( LargerThan(result, A) ) {
738
0
            Abort("Result is larger than the input", opStr);
739
0
        }
740
2.96k
    }
741
}
742
743
147k
void test(const operation::BignumCalc& op, const std::optional<component::Bignum>& result) {
744
147k
    if ( result == std::nullopt ) {
745
93.8k
        return;
746
93.8k
    }
747
748
53.3k
    using namespace BignumCalc;
749
750
53.3k
    const auto calcOp = op.calcOp.Get();
751
752
    /* Negative numbers are not supported yet */
753
53.3k
    if (    op.bn0.IsNegative() ||
754
53.3k
            op.bn1.IsNegative() ||
755
53.3k
            op.bn2.IsNegative() ) {
756
9.80k
        return;
757
9.80k
    }
758
759
    /* Modular calculations are not supported yet */
760
43.5k
    if ( op.modulo != std::nullopt ) {
761
0
        return;
762
0
    }
763
764
43.5k
    switch ( calcOp ) {
765
896
        case    CF_CALCOP("Add(A,B)"):
766
896
            if (    SmallerThan(*result, op.bn0) ||
767
896
                    SmallerThan(*result, op.bn1) ) {
768
0
                Abort("Result is smaller than its operands", repository::CalcOpToString(calcOp));
769
0
            }
770
896
            break;
771
719
        case    CF_CALCOP("Div(A,B)"):
772
719
            if ( IsZero(op.bn1) ) {
773
0
                Abort("Division by zero should not produce a result", repository::CalcOpToString(calcOp));
774
0
            }
775
776
719
            if ( LargerThan(*result, op.bn0) ) {
777
0
                Abort("Result is larger than the dividend", repository::CalcOpToString(calcOp));
778
0
            }
779
719
            break;
780
879
        case    CF_CALCOP("Mul(A,B)"):
781
879
            if ( IsZero(op.bn0) || IsZero(op.bn1) ) {
782
456
                if ( !IsZero(*result) ) {
783
0
                    Abort("Result of Mul with zero operand is not zero", repository::CalcOpToString(calcOp));
784
0
                }
785
456
            }
786
879
            break;
787
1.35k
        case    CF_CALCOP("Mod(A,B)"):
788
1.35k
            BignumCalc::AssertModResult(*result, op.bn1, "Mod");
789
1.35k
            break;
790
8.22k
        case    CF_CALCOP("ExpMod(A,B,C)"):
791
8.22k
            BignumCalc::AssertModResult(*result, op.bn2, "ExpMod");
792
8.22k
            break;
793
306
        case    CF_CALCOP("AddMod(A,B,C)"):
794
306
            BignumCalc::AssertModResult(*result, op.bn2, "AddMod");
795
306
            break;
796
1.94k
        case    CF_CALCOP("SubMod(A,B,C)"):
797
1.94k
            BignumCalc::AssertModResult(*result, op.bn2, "SubMod");
798
1.94k
            break;
799
233
        case    CF_CALCOP("MulMod(A,B,C)"):
800
233
            BignumCalc::AssertModResult(*result, op.bn2, "MulMod");
801
233
            break;
802
309
        case    CF_CALCOP("SqrMod(A,B)"):
803
309
            BignumCalc::AssertModResult(*result, op.bn1, "SqrMod");
804
309
            break;
805
0
        case    CF_CALCOP("SqrtMod(A,B)"):
806
0
            BignumCalc::AssertModResult(*result, op.bn1, "SqrtMod");
807
0
            break;
808
0
        case    CF_CALCOP("ModLShift(A,B,C)"):
809
0
            BignumCalc::AssertModResult(*result, op.bn2, "ModLShift");
810
0
            break;
811
680
        case    CF_CALCOP("Bit(A,B)"):
812
680
            BignumCalc::AssertBinary(*result, "Bit");
813
680
            break;
814
0
        case    CF_CALCOP("IsCoprime(A,B)"):
815
0
            BignumCalc::AssertBinary(*result, "IsCoprime");
816
0
            break;
817
187
        case    CF_CALCOP("IsEq(A,B)"):
818
187
            BignumCalc::AssertBinary(*result, "IsEq");
819
187
            break;
820
74
        case    CF_CALCOP("IsGt(A,B)"):
821
74
            BignumCalc::AssertBinary(*result, "IsGt");
822
74
            break;
823
19
        case    CF_CALCOP("IsGte(A,B)"):
824
19
            BignumCalc::AssertBinary(*result, "IsGte");
825
19
            break;
826
16
        case    CF_CALCOP("IsLt(A,B)"):
827
16
            BignumCalc::AssertBinary(*result, "IsLt");
828
16
            break;
829
20
        case    CF_CALCOP("IsLte(A,B)"):
830
20
            BignumCalc::AssertBinary(*result, "IsLte");
831
20
            break;
832
109
        case    CF_CALCOP("IsEven(A)"):
833
109
            BignumCalc::AssertBinary(*result, "IsEven");
834
109
            break;
835
163
        case    CF_CALCOP("IsOdd(A)"):
836
163
            BignumCalc::AssertBinary(*result, "IsOdd");
837
163
            break;
838
890
        case    CF_CALCOP("IsOne(A)"):
839
890
            BignumCalc::AssertBinary(*result, "IsOne");
840
890
            break;
841
0
        case    CF_CALCOP("IsPow2(A)"):
842
0
            BignumCalc::AssertBinary(*result, "IsPow2");
843
0
            break;
844
358
        case    CF_CALCOP("IsPrime(A)"):
845
358
            BignumCalc::AssertBinary(*result, "IsPrime");
846
358
            break;
847
204
        case    CF_CALCOP("IsZero(A)"):
848
204
            BignumCalc::AssertBinary(*result, "IsZero");
849
204
            break;
850
0
        case    CF_CALCOP("IsSquare(A)"):
851
0
            BignumCalc::AssertBinary(*result, "IsSquare");
852
0
            break;
853
0
        case    CF_CALCOP("IsPower(A)"):
854
0
            BignumCalc::AssertBinary(*result, "IsPower");
855
0
            break;
856
407
        case    CF_CALCOP("Cmp(A,B)"):
857
407
            BignumCalc::AssertTertiary(*result, "Cmp");
858
407
            break;
859
26
        case    CF_CALCOP("CmpAbs(A,B)"):
860
26
            BignumCalc::AssertTertiary(*result, "CmpAbs");
861
26
            break;
862
2.05k
        case    CF_CALCOP("Jacobi(A,B)"):
863
2.05k
            BignumCalc::AssertTertiary(*result, "Jacobi");
864
2.05k
            break;
865
2.08k
        case    CF_CALCOP("Sqr(A)"):
866
2.08k
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
867
2.08k
            break;
868
2.69k
        case    CF_CALCOP("RShift(A,B)"):
869
2.69k
            if ( IsZero(op.bn0) || IsZero(op.bn1) ) {
870
1.65k
                if ( op.bn0.ToTrimmedString() != result->ToTrimmedString() ) {
871
0
                    Abort("Zero operand should not alter input", repository::CalcOpToString(calcOp));
872
0
                }
873
1.65k
            }
874
875
2.69k
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
876
2.69k
            break;
877
450
        case    CF_CALCOP("LShift1(A)"):
878
450
            if ( IsZero(op.bn0) ) {
879
117
                if ( op.bn0.ToTrimmedString() != result->ToTrimmedString() ) {
880
0
                    Abort("Zero input should remain zero", repository::CalcOpToString(calcOp));
881
0
                }
882
117
            }
883
884
450
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
885
450
            break;
886
426
        case    CF_CALCOP("SetBit(A,B)"):
887
426
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
888
426
            break;
889
243
        case    CF_CALCOP("ClearBit(A,B)"):
890
243
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
891
243
            break;
892
32
        case    CF_CALCOP("Sqrt(A)"):
893
32
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
894
32
            break;
895
0
        case    CF_CALCOP("Cbrt(A)"):
896
0
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
897
0
            break;
898
589
        case    CF_CALCOP("MulAdd(A,B,C)"):
899
589
            AssertNotSmallerThan(*result, op.bn2, repository::CalcOpToString(calcOp));
900
589
            break;
901
0
        case    CF_CALCOP("Min(A,B)"):
902
0
        case    CF_CALCOP("Max(A,B)"):
903
0
            if ( !IsEqual(*result, op.bn0) && !IsEqual(*result, op.bn1) ) {
904
0
                Abort("Result is not an operand", repository::CalcOpToString(calcOp));
905
0
            }
906
0
            break;
907
0
        case    CF_CALCOP("Mask(A,B)"):
908
0
            if ( LargerThan(*result, op.bn0) ) {
909
0
                Abort("Result is larger than input", repository::CalcOpToString(calcOp));
910
0
            }
911
0
            break;
912
0
        case    CF_CALCOP("And(A,B)"):
913
0
            AssertNotLargerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
914
0
            AssertNotLargerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
915
0
            break;
916
0
        case    CF_CALCOP("Or(A,B)"):
917
0
            AssertNotSmallerThan(*result, op.bn0, repository::CalcOpToString(calcOp));
918
0
            AssertNotSmallerThan(*result, op.bn1, repository::CalcOpToString(calcOp));
919
0
            break;
920
0
        case    CF_CALCOP("Nthrt(A,B)"):
921
0
        case    CF_CALCOP("NthrtRem(A,B)"):
922
0
            if ( IsZero(op.bn1) ) {
923
0
                Abort("Root of zero should not produce a result", repository::CalcOpToString(calcOp));
924
0
            }
925
0
            break;
926
43.5k
    }
927
43.5k
}
928
929
90
void test(const operation::BignumCalc_Fp2& op, const std::optional<component::Fp2>& result) {
930
90
    (void)op;
931
90
    (void)result;
932
90
}
933
934
303
void test(const operation::BignumCalc_Fp12& op, const std::optional<component::Fp12>& result) {
935
303
    (void)op;
936
303
    (void)result;
937
303
}
938
939
} /* namespace tests */
940
} /* namespace cryptofuzz */