Coverage Report

Created: 2026-10-17 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptofuzz/modules/relic/module.cpp
Line
Count
Source
1
#include "module.h"
2
#include "bn_ops.h"
3
#include <cryptofuzz/util.h>
4
5
extern "C" {
6
    #include <relic_conf.h>
7
    #include <relic.h>
8
}
9
10
namespace cryptofuzz {
11
namespace module {
12
namespace relic_detail {
13
    Datasource* global_ds = nullptr;
14
15
28.9k
    void relic_fuzzer_rng(uint8_t* out, size_t size, void*) {
16
28.9k
        CF_ASSERT(global_ds != nullptr, "Global datasource is NULL");
17
18
28.9k
        if ( size == 0 ) {
19
0
            return;
20
0
        }
21
22
28.9k
        try {
23
28.9k
            const auto data = global_ds->GetData(0, size, size);
24
28.9k
            CF_ASSERT(data.size() == (size_t)size, "Unexpected data size");
25
28.9k
            memcpy(out, data.data(), size);
26
27
28.9k
            return;
28
28.9k
        } catch ( ... ) { }
29
30
326
        memset(out, 0xAA, size);
31
326
    }
32
}
33
}
34
}
35
36
namespace cryptofuzz {
37
namespace module {
38
39
relic::relic(void) :
40
2
    Module("relic") {
41
42
2
    CF_ASSERT(core_init() == RLC_OK, "Cannot initialize relic");
43
2
    /* noret */ rand_seed(relic_detail::relic_fuzzer_rng, nullptr);
44
2
}
45
46
namespace relic_detail {
47
4.37k
    static bool SetCurve(const component::CurveType curveType) {
48
49
        /* TODO enable disabled curves in the relic build */
50
51
4.37k
        switch ( curveType.Get() ) {
52
#if 0
53
            case    CF_ECC_CURVE("secp192r1"):
54
                /* noret */ ep_param_set(NIST_P192);
55
                return true;
56
#endif
57
#if 0
58
            case    CF_ECC_CURVE("secp224r1"):
59
                /* noret */ ep_param_set(NIST_P224);
60
                return true;
61
#endif
62
2.09k
            case    CF_ECC_CURVE("secp256r1"):
63
2.09k
                /* noret */ ep_param_set(NIST_P256);
64
2.09k
                return true;
65
#if 0
66
            case    CF_ECC_CURVE("secp384r1"):
67
                /* noret */ ep_param_set(NIST_P384);
68
                return true;
69
#endif
70
#if 0
71
            case    CF_ECC_CURVE("secp521r1"):
72
                /* noret */ ep_param_set(NIST_P521);
73
                return true;
74
#endif
75
#if 0
76
            case    CF_ECC_CURVE("secp160k1"):
77
                /* noret */ ep_param_set(SECG_K160);
78
                return true;
79
#endif
80
#if 0
81
            case    CF_ECC_CURVE("secp192k1"):
82
                /* noret */ ep_param_set(SECG_K192);
83
                return true;
84
#endif
85
2.28k
            case    CF_ECC_CURVE("secp256k1"):
86
2.28k
                /* noret */ ep_param_set(SECG_K256);
87
2.28k
                return true;
88
0
            default:
89
0
                return false;
90
4.37k
        }
91
4.37k
    }
92
}
93
94
1.69k
std::optional<component::Digest> relic::OpDigest(operation::Digest& op) {
95
1.69k
    std::optional<component::Digest> ret = std::nullopt;
96
1.69k
    switch ( op.digestType.Get() ) {
97
199
        case    CF_DIGEST("SHA224"):
98
199
            {
99
199
                uint8_t out[28];
100
199
                CF_NORET(md_map_sh224(out, op.cleartext.GetPtr(), op.cleartext.GetSize()));
101
199
                ret = component::Digest(out, 28);
102
199
            }
103
199
            break;
104
119
        case    CF_DIGEST("SHA256"):
105
119
            {
106
119
                uint8_t out[32];
107
119
                CF_NORET(md_map_sh256(out, op.cleartext.GetPtr(), op.cleartext.GetSize()));
108
119
                ret = component::Digest(out, 32);
109
119
            }
110
119
            break;
111
445
        case    CF_DIGEST("SHA384"):
112
445
            {
113
445
                uint8_t out[48];
114
445
                CF_NORET(md_map_sh384(out, op.cleartext.GetPtr(), op.cleartext.GetSize()));
115
445
                ret = component::Digest(out, 48);
116
445
            }
117
445
            break;
118
426
        case    CF_DIGEST("SHA512"):
119
426
            {
120
426
                uint8_t out[64];
121
426
                CF_NORET(md_map_sh512(out, op.cleartext.GetPtr(), op.cleartext.GetSize()));
122
426
                ret = component::Digest(out, 64);
123
426
            }
124
426
            break;
125
274
        case    CF_DIGEST("BLAKE2S160"):
126
274
            {
127
274
                uint8_t out[20];
128
274
                CF_NORET(md_map_b2s160(out, op.cleartext.GetPtr(), op.cleartext.GetSize()));
129
274
                ret = component::Digest(out, 20);
130
274
            }
131
274
            break;
132
167
        case    CF_DIGEST("BLAKE2S256"):
133
167
            {
134
167
                uint8_t out[32];
135
167
                CF_NORET(md_map_b2s256(out, op.cleartext.GetPtr(), op.cleartext.GetSize()));
136
167
                ret = component::Digest(out, 32);
137
167
            }
138
167
            break;
139
1.69k
    }
140
141
1.69k
    return ret;
142
1.69k
}
143
144
510
std::optional<component::MAC> relic::OpHMAC(operation::HMAC& op) {
145
510
    std::optional<component::MAC> ret = std::nullopt;
146
510
#if MD_MAP == SH256
147
510
    if ( op.digestType.Is(CF_DIGEST("SHA256")) ) {
148
219
        uint8_t mac[RLC_MD_LEN];
149
219
        CF_NORET(md_hmac(mac, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.key.GetPtr(), op.cipher.key.GetSize()));
150
219
        ret = component::MAC(mac, sizeof(mac));
151
219
    }
152
#else
153
    (void)op;
154
#endif
155
510
    return ret;
156
510
}
157
158
574
std::optional<component::Ciphertext> relic::OpSymmetricEncrypt(operation::SymmetricEncrypt& op) {
159
574
    std::optional<component::Ciphertext> ret = std::nullopt;
160
161
574
    uint8_t* out = nullptr;
162
163
574
    switch ( op.cipher.cipherType.Get() ) {
164
173
        case CF_CIPHER("AES_128_CBC"):
165
417
        case CF_CIPHER("AES_192_CBC"):
166
574
        case CF_CIPHER("AES_256_CBC"):
167
574
            {
168
574
                CF_CHECK_EQ(op.cipher.iv.GetSize(), 16);
169
371
                size_t outSize = static_cast<int>(op.ciphertextSize);
170
371
                out = util::malloc(op.ciphertextSize);
171
371
                CF_CHECK_EQ(
172
371
                        bc_aes_cbc_enc(
173
371
                            out, &outSize,
174
371
                            (uint8_t*)op.cleartext.GetPtr(), op.cleartext.GetSize(),
175
371
                            (uint8_t*)op.cipher.key.GetPtr(), op.cipher.key.GetSize(),
176
371
                            (uint8_t*)op.cipher.iv.GetPtr()), RLC_OK);
177
303
                ret = component::Ciphertext(Buffer(out, outSize));
178
303
            }
179
0
            break;
180
574
    }
181
182
574
end:
183
574
    util::free(out);
184
185
574
    return ret;
186
574
}
187
188
776
std::optional<component::Cleartext> relic::OpSymmetricDecrypt(operation::SymmetricDecrypt& op) {
189
776
    std::optional<component::Cleartext> ret = std::nullopt;
190
191
776
    uint8_t* out = nullptr;
192
193
776
    switch ( op.cipher.cipherType.Get() ) {
194
312
        case CF_CIPHER("AES_128_CBC"):
195
513
        case CF_CIPHER("AES_192_CBC"):
196
776
        case CF_CIPHER("AES_256_CBC"):
197
776
            {
198
776
                CF_CHECK_EQ(op.cipher.iv.GetSize(), 16);
199
607
                size_t outSize = static_cast<int>(op.cleartextSize);
200
607
                out = util::malloc(op.cleartextSize);
201
607
                CF_CHECK_EQ(
202
607
                        bc_aes_cbc_dec(
203
607
                            out, &outSize,
204
607
                            (uint8_t*)op.ciphertext.GetPtr(), op.ciphertext.GetSize(),
205
607
                            (uint8_t*)op.cipher.key.GetPtr(), op.cipher.key.GetSize(),
206
607
                            (uint8_t*)op.cipher.iv.GetPtr()), RLC_OK);
207
438
                ret = component::Cleartext(Buffer(out, outSize));
208
438
            }
209
0
            break;
210
776
    }
211
212
776
end:
213
776
    util::free(out);
214
215
776
    return ret;
216
776
}
217
218
342
std::optional<component::Key> relic::OpKDF_X963(operation::KDF_X963& op) {
219
342
    std::optional<component::Key> ret = std::nullopt;
220
342
#if MD_MAP == SH256
221
342
    uint8_t* key = nullptr;
222
223
342
    if ( op.digestType.Is(CF_DIGEST("SHA256")) ) {
224
285
        if ( op.info.GetSize() == 0 ) {
225
230
            key = util::malloc(op.keySize);
226
230
            CF_NORET(md_kdf(key, op.keySize, op.secret.GetPtr(), op.secret.GetSize()));
227
230
            ret = component::Key(key, op.keySize);
228
230
        }
229
285
    }
230
231
342
    util::free(key);
232
#else
233
    (void)op;
234
#endif
235
342
    return ret;
236
342
}
237
238
1.47k
std::optional<component::ECC_PublicKey> relic::OpECC_PrivateToPublic(operation::ECC_PrivateToPublic& op) {
239
1.47k
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
240
1.47k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
241
242
1.47k
    ec_t pub;
243
1.47k
    bool pub_initialized = false;
244
1.47k
    relic_bignum::Bignum priv(ds), order(ds);
245
246
    /* Set curve */
247
1.47k
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
248
249
    /* Set private key */
250
1.47k
    CF_CHECK_TRUE(priv.Set(op.priv.ToString()));
251
252
    /* Check if private key is valid */
253
1.47k
    {
254
        /* Must not be zero */
255
1.47k
        CF_CHECK_EQ(bn_is_zero(priv.Get()), 0);
256
257
        /* Must be less than curve order */
258
1.42k
        /* noret */ ec_curve_get_ord(order.Get());
259
1.42k
        CF_CHECK_EQ(bn_cmp(priv.Get(), order.Get()), RLC_LT);
260
1.36k
    }
261
262
    /* Compute pubkey */
263
1.36k
    /* noret */ ec_new(pub);
264
1.36k
    pub_initialized = true;
265
266
1.36k
    RLC_TRY {
267
1.36k
        /* noret */ ec_mul_gen(pub, priv.Get());
268
2.73k
    } RLC_CATCH_ANY {
269
0
        goto end;
270
0
    }
271
1.36k
    CF_CHECK_NE(ec_is_infty(pub), 1);
272
273
1.36k
    {
274
1.36k
        const int size = ec_size_bin(pub, 0);
275
1.36k
        CF_ASSERT(size > 1, "Pubkey has invalid size");
276
1.36k
        CF_ASSERT((size % 2) == 1, "Pubkey has invalid size");
277
1.36k
        uint8_t* out = util::malloc(size);
278
1.36k
        ec_write_bin(out, size, pub, 0);
279
280
1.36k
        CF_ASSERT(out[0] == 0x04, "pubkey not DER encoded");
281
282
1.36k
        const auto halfSize = (size-1) / 2;
283
1.36k
        const auto X = util::BinToDec(out + 1, halfSize);
284
1.36k
        const auto Y = util::BinToDec(out + 1 + halfSize, halfSize);
285
286
1.36k
        util::free(out);
287
288
1.36k
        ret = {X, Y};
289
1.36k
    }
290
291
1.47k
end:
292
1.47k
    if ( pub_initialized ) {
293
1.36k
        ec_free(pub);
294
1.36k
    }
295
1.47k
    return ret;
296
1.36k
}
297
298
756
std::optional<bool> relic::OpECDSA_Verify(operation::ECDSA_Verify& op) {
299
756
    std::optional<bool> ret = std::nullopt;
300
756
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
301
302
756
    if ( !op.digestType.Is({CF_DIGEST("NULL"), CF_DIGEST("SHA256")}) ) {
303
184
        return ret;
304
184
    }
305
306
572
    ec_t pub;
307
572
    bool pub_initialized = false;
308
572
    relic_bignum::Bignum r(ds), s(ds);
309
572
    std::vector<uint8_t> pub_bytes;
310
311
    /* Set curve */
312
572
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
313
314
    /* Set signature */
315
572
    CF_CHECK_TRUE(r.Set(op.signature.signature.first.ToString()));
316
572
    CF_CHECK_TRUE(s.Set(op.signature.signature.second.ToString()));
317
318
    /* Set pubkey */
319
572
    {
320
572
        /* noret */ ec_new(pub);
321
572
        pub_initialized = true;
322
572
        const int size = 65;
323
572
        const auto halfSize = (size-1) / 2;
324
325
572
        std::optional<std::vector<uint8_t>> pub_x, pub_y;
326
572
        CF_CHECK_NE(pub_x = util::DecToBin(op.signature.pub.first.ToTrimmedString(), halfSize), std::nullopt);
327
562
        CF_CHECK_NE(pub_y = util::DecToBin(op.signature.pub.second.ToTrimmedString(), halfSize), std::nullopt);
328
329
552
        pub_bytes.push_back(0x04);
330
552
        pub_bytes.insert(std::end(pub_bytes), std::begin(*pub_x), std::end(*pub_x));
331
552
        pub_bytes.insert(std::end(pub_bytes), std::begin(*pub_y), std::end(*pub_y));
332
333
552
        /* noret */ ec_read_bin(pub, pub_bytes.data(), size);
334
552
    }
335
336
0
    {
337
552
        Buffer CT = op.cleartext;
338
339
552
        if ( op.digestType.Is(CF_DIGEST("SHA256")) ) {
340
213
            CT = CT.SHA256();
341
213
        }
342
343
552
        CT = CT.ECDSA_RandomPad(ds, op.curveType);
344
345
552
        auto CTref = CT.GetVectorPtr();
346
347
552
        ret = cp_ecdsa_ver(r.Get(), s.Get(), CTref.data(), CTref.size(), 1, pub) == 1;
348
552
    }
349
350
572
end:
351
572
    if ( pub_initialized ) {
352
572
        ec_free(pub);
353
572
    }
354
572
    return ret;
355
552
}
356
357
329
std::optional<bool> relic::OpECC_ValidatePubkey(operation::ECC_ValidatePubkey& op) {
358
329
    std::optional<bool> ret = std::nullopt;
359
360
329
    ec_t pub;
361
329
    bool pub_initialized = false;
362
329
    std::vector<uint8_t> pub_bytes;
363
364
    /* Set curve */
365
329
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
366
367
    /* Set pubkey */
368
329
    {
369
329
        /* noret */ ec_new(pub);
370
329
        pub_initialized = true;
371
329
        const int size = 65;
372
329
        const auto halfSize = (size-1) / 2;
373
374
329
        std::optional<std::vector<uint8_t>> pub_x, pub_y;
375
329
        CF_CHECK_NE(pub_x = util::DecToBin(op.pub.first.ToTrimmedString(), halfSize), std::nullopt);
376
305
        CF_CHECK_NE(pub_y = util::DecToBin(op.pub.second.ToTrimmedString(), halfSize), std::nullopt);
377
378
274
        pub_bytes.push_back(0x04);
379
274
        pub_bytes.insert(std::end(pub_bytes), std::begin(*pub_x), std::end(*pub_x));
380
274
        pub_bytes.insert(std::end(pub_bytes), std::begin(*pub_y), std::end(*pub_y));
381
382
274
        /* noret */ ec_read_bin(pub, pub_bytes.data(), size);
383
274
    }
384
385
274
    ret = ec_on_curve(pub);
386
387
329
end:
388
329
    if ( pub_initialized ) {
389
329
        ec_free(pub);
390
329
    }
391
329
    return ret;
392
274
}
393
394
1.12k
std::optional<component::ECDSA_Signature> relic::OpECDSA_Sign(operation::ECDSA_Sign& op) {
395
1.12k
    std::optional<component::ECDSA_Signature> ret = std::nullopt;
396
1.12k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
397
398
1.12k
    if ( op.UseRandomNonce() == false ) {
399
587
        return ret;
400
587
    }
401
535
    if ( !op.digestType.Is({CF_DIGEST("NULL"), CF_DIGEST("SHA256")}) ) {
402
14
        return ret;
403
14
    }
404
405
521
    relic_detail::global_ds = &ds;
406
407
521
    ec_t pub;
408
521
    bool pub_initialized = false;
409
521
    relic_bignum::Bignum priv(ds), r(ds), s(ds);
410
521
    std::optional<std::string> R, S;
411
521
    std::string X, Y;
412
413
    /* Set curve */
414
521
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
415
416
    /* Set privkey */
417
521
    CF_CHECK_TRUE(priv.Set(op.priv.ToString()));
418
521
    CF_CHECK_EQ(bn_is_zero(priv.Get()), 0);
419
420
421
422
508
    {
423
508
        Buffer CT = op.cleartext;
424
425
508
        if ( op.digestType.Is(CF_DIGEST("SHA256")) ) {
426
207
            CT = CT.SHA256();
427
207
        }
428
429
508
        CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
430
431
508
        auto CTref = CT.GetVectorPtr();
432
433
508
        CF_CHECK_EQ(cp_ecdsa_sig(r.Get(), s.Get(), CTref.data(), CTref.size(), 1, priv.Get()), 0);
434
93
    }
435
436
93
    CF_CHECK_NE(R = r.ToString(), std::nullopt);
437
93
    CF_CHECK_NE(S = s.ToString(), std::nullopt);
438
439
    /* Compute pubkey */
440
93
    /* noret */ ec_new(pub);
441
93
    pub_initialized = true;
442
93
    RLC_TRY {
443
93
        /* noret */ ec_mul_gen(pub, priv.Get());
444
186
    } RLC_CATCH_ANY {
445
0
        goto end;
446
0
    }
447
93
    CF_CHECK_NE(ec_is_infty(pub), 1);
448
449
90
    {
450
90
        auto ct = op.cleartext.Get();
451
452
90
        CF_ASSERT(cp_ecdsa_ver(r.Get(), s.Get(), ct.data(), ct.size(), 1, pub) == 1, "Cannot verify generated signature");
453
90
    }
454
455
0
    {
456
90
        const int size = ec_size_bin(pub, 0);
457
90
        CF_ASSERT(size > 1, "Pubkey has invalid size");
458
90
        CF_ASSERT((size % 2) == 1, "Pubkey has invalid size");
459
90
        uint8_t* out = util::malloc(size);
460
90
        ec_write_bin(out, size, pub, 0);
461
462
90
        CF_ASSERT(out[0] == 0x04, "pubkey not DER encoded");
463
464
90
        const auto halfSize = (size-1) / 2;
465
90
        X = util::BinToDec(out + 1, halfSize);
466
90
        Y = util::BinToDec(out + 1 + halfSize, halfSize);
467
468
90
        util::free(out);
469
90
    }
470
471
0
    ret = { {*R, *S}, {X, Y} };
472
473
521
end:
474
521
    if ( pub_initialized ) {
475
93
        ec_free(pub);
476
93
    }
477
521
    relic_detail::global_ds = nullptr;
478
479
521
    return ret;
480
90
}
481
482
155
std::optional<component::ECC_Point> relic::OpECC_Point_Add(operation::ECC_Point_Add& op) {
483
155
    std::optional<component::ECC_Point> ret = std::nullopt;
484
485
155
    ec_t a, b, res;
486
155
    bool a_initialized = false, b_initialized = false, res_initialized = false;
487
155
    std::vector<uint8_t> a_bytes, b_bytes;
488
489
    /* Set curve */
490
155
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
491
492
    /* Set A */
493
155
    {
494
155
        /* noret */ ec_new(a);
495
155
        a_initialized = true;
496
497
155
        std::optional<std::vector<uint8_t>> x, y;
498
155
        CF_CHECK_NE(x = util::DecToBin(op.a.first.ToTrimmedString(), 32), std::nullopt);
499
144
        CF_CHECK_NE(y = util::DecToBin(op.a.second.ToTrimmedString(), 32), std::nullopt);
500
501
134
        a_bytes.push_back(0x04);
502
134
        a_bytes.insert(std::end(a_bytes), std::begin(*x), std::end(*x));
503
134
        a_bytes.insert(std::end(a_bytes), std::begin(*y), std::end(*y));
504
505
134
        /* noret */ ec_read_bin(a, a_bytes.data(), 65);
506
507
134
        CF_CHECK_NE(ec_on_curve(a), 0)
508
134
    }
509
510
    /* Set B */
511
87
    {
512
87
        /* noret */ ec_new(b);
513
87
        b_initialized = true;
514
515
87
        std::optional<std::vector<uint8_t>> x, y;
516
87
        CF_CHECK_NE(x = util::DecToBin(op.b.first.ToTrimmedString(), 32), std::nullopt);
517
77
        CF_CHECK_NE(y = util::DecToBin(op.b.second.ToTrimmedString(), 32), std::nullopt);
518
519
65
        b_bytes.push_back(0x04);
520
65
        b_bytes.insert(std::end(b_bytes), std::begin(*x), std::end(*x));
521
65
        b_bytes.insert(std::end(b_bytes), std::begin(*y), std::end(*y));
522
523
65
        /* noret */ ec_read_bin(b, b_bytes.data(), 65);
524
525
65
        CF_CHECK_NE(ec_on_curve(b), 0)
526
65
    }
527
528
    /* Add */
529
34
    /* noret */ ec_new(res);
530
34
    res_initialized = true;
531
34
    ec_add(res, a, b);
532
533
34
    {
534
34
        uint8_t* out = util::malloc(65);
535
34
        ec_write_bin(out, 65, res, 0);
536
537
34
        const auto X = util::BinToDec(out + 1, 32);
538
34
        const auto Y = util::BinToDec(out + 1 + 32, 32);
539
540
34
        util::free(out);
541
542
34
        ret = {X, Y};
543
34
    }
544
545
155
end:
546
155
    if ( a_initialized ) {
547
155
        ec_free(a);
548
155
    }
549
155
    if ( b_initialized ) {
550
87
        ec_free(b);
551
87
    }
552
155
    if ( res_initialized ) {
553
34
        ec_free(res);
554
34
    }
555
556
155
    return ret;
557
34
}
558
559
534
std::optional<component::ECC_Point> relic::OpECC_Point_Mul(operation::ECC_Point_Mul& op) {
560
534
    std::optional<component::ECC_Point> ret = std::nullopt;
561
534
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
562
563
534
    relic_bignum::Bignum b(ds);
564
534
    ec_t a, res;
565
534
    bool a_initialized = false, res_initialized = false;
566
534
    std::vector<uint8_t> a_bytes;
567
568
    /* Set curve */
569
534
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
570
571
    /* Set A */
572
534
    {
573
534
        /* noret */ ec_new(a);
574
534
        a_initialized = true;
575
576
534
        std::optional<std::vector<uint8_t>> x, y;
577
534
        CF_CHECK_NE(x = util::DecToBin(op.a.first.ToTrimmedString(), 32), std::nullopt);
578
523
        CF_CHECK_NE(y = util::DecToBin(op.a.second.ToTrimmedString(), 32), std::nullopt);
579
580
513
        a_bytes.push_back(0x04);
581
513
        a_bytes.insert(std::end(a_bytes), std::begin(*x), std::end(*x));
582
513
        a_bytes.insert(std::end(a_bytes), std::begin(*y), std::end(*y));
583
584
513
        /* noret */ ec_read_bin(a, a_bytes.data(), 65);
585
586
513
        CF_CHECK_NE(ec_on_curve(a), 0)
587
513
    }
588
589
    /* Set B */
590
439
    CF_CHECK_TRUE(b.Set(op.b.ToString()));
591
592
    /* Multiply */
593
439
    /* noret */ ec_new(res);
594
439
    res_initialized = true;
595
439
    ec_mul(res, a, b.Get());
596
597
439
    {
598
439
        uint8_t* out = util::malloc(65);
599
439
        ec_write_bin(out, 65, res, 0);
600
601
439
        const auto X = util::BinToDec(out + 1, 32);
602
439
        const auto Y = util::BinToDec(out + 1 + 32, 32);
603
604
439
        util::free(out);
605
606
439
        ret = {X, Y};
607
439
    }
608
609
534
end:
610
534
    if ( a_initialized ) {
611
534
        ec_free(a);
612
534
    }
613
534
    if ( res_initialized ) {
614
439
        ec_free(res);
615
439
    }
616
617
534
    return ret;
618
439
}
619
620
505
std::optional<component::ECC_Point> relic::OpECC_Point_Dbl(operation::ECC_Point_Dbl& op) {
621
505
    std::optional<component::ECC_Point> ret = std::nullopt;
622
505
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
623
624
505
    ec_t a, res;
625
505
    bool a_initialized = false, res_initialized = false;
626
505
    std::vector<uint8_t> a_bytes;
627
628
    /* Set curve */
629
505
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
630
631
    /* Set A */
632
505
    {
633
505
        /* noret */ ec_new(a);
634
505
        a_initialized = true;
635
636
505
        std::optional<std::vector<uint8_t>> x, y;
637
505
        CF_CHECK_NE(x = util::DecToBin(op.a.first.ToTrimmedString(), 32), std::nullopt);
638
487
        CF_CHECK_NE(y = util::DecToBin(op.a.second.ToTrimmedString(), 32), std::nullopt);
639
640
469
        a_bytes.push_back(0x04);
641
469
        a_bytes.insert(std::end(a_bytes), std::begin(*x), std::end(*x));
642
469
        a_bytes.insert(std::end(a_bytes), std::begin(*y), std::end(*y));
643
644
469
        /* noret */ ec_read_bin(a, a_bytes.data(), 65);
645
646
469
        CF_CHECK_NE(ec_on_curve(a), 0)
647
469
    }
648
649
    /* Double */
650
154
    /* noret */ ec_new(res);
651
154
    res_initialized = true;
652
154
    ec_dbl(res, a);
653
654
154
    {
655
154
        uint8_t* out = util::malloc(65);
656
154
        ec_write_bin(out, 65, res, 0);
657
658
154
        const auto X = util::BinToDec(out + 1, 32);
659
154
        const auto Y = util::BinToDec(out + 1 + 32, 32);
660
661
154
        util::free(out);
662
663
154
        ret = {X, Y};
664
154
    }
665
666
505
end:
667
505
    if ( a_initialized ) {
668
505
        ec_free(a);
669
505
    }
670
505
    if ( res_initialized ) {
671
154
        ec_free(res);
672
154
    }
673
674
505
    return ret;
675
154
}
676
677
287
std::optional<component::ECC_Point> relic::OpECC_Point_Neg(operation::ECC_Point_Neg& op) {
678
287
    std::optional<component::ECC_Point> ret = std::nullopt;
679
287
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
680
681
287
    ec_t a, res;
682
287
    bool a_initialized = false, res_initialized = false;
683
287
    std::vector<uint8_t> a_bytes;
684
685
    /* Set curve */
686
287
    CF_CHECK_TRUE(relic_detail::SetCurve(op.curveType));
687
688
    /* Set A */
689
287
    {
690
287
        /* noret */ ec_new(a);
691
287
        a_initialized = true;
692
693
287
        std::optional<std::vector<uint8_t>> x, y;
694
287
        CF_CHECK_NE(x = util::DecToBin(op.a.first.ToTrimmedString(), 32), std::nullopt);
695
254
        CF_CHECK_NE(y = util::DecToBin(op.a.second.ToTrimmedString(), 32), std::nullopt);
696
697
241
        a_bytes.push_back(0x04);
698
241
        a_bytes.insert(std::end(a_bytes), std::begin(*x), std::end(*x));
699
241
        a_bytes.insert(std::end(a_bytes), std::begin(*y), std::end(*y));
700
701
241
        /* noret */ ec_read_bin(a, a_bytes.data(), 65);
702
703
241
        CF_CHECK_NE(ec_on_curve(a), 0)
704
241
    }
705
706
    /* Negate */
707
44
    /* noret */ ec_new(res);
708
44
    res_initialized = true;
709
44
    ec_neg(res, a);
710
711
44
    {
712
44
        uint8_t* out = util::malloc(65);
713
44
        ec_write_bin(out, 65, res, 0);
714
715
44
        const auto X = util::BinToDec(out + 1, 32);
716
44
        const auto Y = util::BinToDec(out + 1 + 32, 32);
717
718
44
        util::free(out);
719
720
44
        ret = {X, Y};
721
44
    }
722
723
287
end:
724
287
    if ( a_initialized ) {
725
287
        ec_free(a);
726
287
    }
727
287
    if ( res_initialized ) {
728
44
        ec_free(res);
729
44
    }
730
731
287
    return ret;
732
44
}
733
734
5.56k
std::optional<component::Bignum> relic::OpBignumCalc(operation::BignumCalc& op) {
735
5.56k
    std::optional<component::Bignum> ret = std::nullopt;
736
5.56k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
737
738
5.56k
    relic_bignum::Bignum res(ds);
739
5.56k
    std::vector<relic_bignum::Bignum> bn = {
740
5.56k
        std::move(relic_bignum::Bignum(ds)),
741
5.56k
        std::move(relic_bignum::Bignum(ds)),
742
5.56k
        std::move(relic_bignum::Bignum(ds)),
743
5.56k
        std::move(relic_bignum::Bignum(ds)),
744
5.56k
    };
745
746
5.56k
    std::unique_ptr<relic_bignum::Operation> opRunner = nullptr;
747
748
5.56k
    CF_CHECK_TRUE(res.Set("0"));
749
5.56k
    CF_CHECK_TRUE(bn[0].Set(op.bn0.ToString(ds)));
750
5.56k
    CF_CHECK_TRUE(bn[1].Set(op.bn1.ToString(ds)));
751
5.56k
    CF_CHECK_TRUE(bn[2].Set(op.bn2.ToString(ds)));
752
5.56k
    CF_CHECK_TRUE(bn[3].Set(op.bn3.ToString(ds)));
753
754
5.56k
    switch ( op.calcOp.Get() ) {
755
45
        case    CF_CALCOP("Add(A,B)"):
756
45
            opRunner = std::make_unique<relic_bignum::Add>();
757
45
            break;
758
109
        case    CF_CALCOP("Sub(A,B)"):
759
109
            opRunner = std::make_unique<relic_bignum::Sub>();
760
109
            break;
761
140
        case    CF_CALCOP("Mul(A,B)"):
762
140
            opRunner = std::make_unique<relic_bignum::Mul>();
763
140
            break;
764
297
        case    CF_CALCOP("Sqr(A)"):
765
297
            opRunner = std::make_unique<relic_bignum::Sqr>();
766
297
            break;
767
95
        case    CF_CALCOP("Div(A,B)"):
768
95
            opRunner = std::make_unique<relic_bignum::Div>();
769
95
            break;
770
954
        case    CF_CALCOP("GCD(A,B)"):
771
954
            opRunner = std::make_unique<relic_bignum::GCD>();
772
954
            break;
773
0
        case    CF_CALCOP("ExtGCD_X(A,B)"):
774
0
            opRunner = std::make_unique<relic_bignum::ExtGCD_X>();
775
0
            break;
776
0
        case    CF_CALCOP("ExtGCD_Y(A,B)"):
777
0
            opRunner = std::make_unique<relic_bignum::ExtGCD_Y>();
778
0
            break;
779
345
        case    CF_CALCOP("LCM(A,B)"):
780
345
            opRunner = std::make_unique<relic_bignum::LCM>();
781
345
            break;
782
253
        case    CF_CALCOP("InvMod(A,B)"):
783
253
            opRunner = std::make_unique<relic_bignum::InvMod>();
784
253
            break;
785
60
        case    CF_CALCOP("LShift1(A)"):
786
60
            opRunner = std::make_unique<relic_bignum::LShift1>();
787
60
            break;
788
507
        case    CF_CALCOP("Jacobi(A,B)"):
789
507
            opRunner = std::make_unique<relic_bignum::Jacobi>();
790
507
            break;
791
33
        case    CF_CALCOP("Cmp(A,B)"):
792
33
            opRunner = std::make_unique<relic_bignum::Cmp>();
793
33
            break;
794
281
        case    CF_CALCOP("Mod(A,B)"):
795
281
            opRunner = std::make_unique<relic_bignum::Mod>();
796
281
            break;
797
30
        case    CF_CALCOP("IsEven(A)"):
798
30
            opRunner = std::make_unique<relic_bignum::IsEven>();
799
30
            break;
800
22
        case    CF_CALCOP("IsOdd(A)"):
801
22
            opRunner = std::make_unique<relic_bignum::IsOdd>();
802
22
            break;
803
20
        case    CF_CALCOP("IsZero(A)"):
804
20
            opRunner = std::make_unique<relic_bignum::IsZero>();
805
20
            break;
806
53
        case    CF_CALCOP("Neg(A)"):
807
53
            opRunner = std::make_unique<relic_bignum::Neg>();
808
53
            break;
809
385
        case    CF_CALCOP("Sqrt(A)"):
810
385
            opRunner = std::make_unique<relic_bignum::Sqrt>();
811
385
            break;
812
17
        case    CF_CALCOP("Abs(A)"):
813
17
            opRunner = std::make_unique<relic_bignum::Abs>();
814
17
            break;
815
1.28k
        case    CF_CALCOP("ExpMod(A,B,C)"):
816
1.28k
            opRunner = std::make_unique<relic_bignum::ExpMod>();
817
1.28k
            break;
818
10
        case    CF_CALCOP("NumBits(A)"):
819
10
            opRunner = std::make_unique<relic_bignum::NumBits>();
820
10
            break;
821
42
        case    CF_CALCOP("CmpAbs(A,B)"):
822
42
            opRunner = std::make_unique<relic_bignum::CmpAbs>();
823
42
            break;
824
171
        case    CF_CALCOP("RShift(A,B)"):
825
171
            opRunner = std::make_unique<relic_bignum::RShift>();
826
171
            break;
827
151
        case    CF_CALCOP("Bit(A,B)"):
828
151
            opRunner = std::make_unique<relic_bignum::Bit>();
829
151
            break;
830
108
        case    CF_CALCOP("SetBit(A,B)"):
831
108
            opRunner = std::make_unique<relic_bignum::SetBit>();
832
108
            break;
833
151
        case    CF_CALCOP("ClearBit(A,B)"):
834
151
            opRunner = std::make_unique<relic_bignum::ClearBit>();
835
151
            break;
836
5.56k
    }
837
838
5.56k
    CF_CHECK_NE(opRunner, nullptr);
839
5.56k
    CF_CHECK_EQ(opRunner->Run(ds, res, bn), true);
840
841
4.68k
    ret = res.ToComponentBignum();
842
843
5.56k
end:
844
5.56k
    return ret;
845
4.68k
}
846
847
} /* namespace module */
848
} /* namespace cryptofuzz */