Coverage Report

Created: 2026-06-07 07:04

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