Coverage Report

Created: 2023-02-22 06:39

/src/cryptofuzz/modules/wolfcrypt/ecdsa_generic.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "ecdsa_generic.h"
2
#include "module_internal.h"
3
#include "shared.h"
4
#include "bn_ops.h"
5
#include <cryptofuzz/util.h>
6
#include <iostream>
7
8
namespace cryptofuzz {
9
namespace module {
10
namespace wolfCrypt_detail {
11
12
#if !defined(WOLFSSL_SP_MATH)
13
#include "custom_curves.h"
14
#endif
15
16
#if defined(CRYPTOFUZZ_WOLFCRYPT_ALLOCATION_FAILURES)
17
    extern bool haveAllocFailure;
18
#endif
19
20
WC_RNG* GetRNG(void);
21
22
ECCKey::ECCKey(Datasource& ds) :
23
1.35k
    ds(ds) {
24
1.35k
    if ( (key = wc_ecc_key_new(nullptr)) == nullptr ) {
25
133
        throw std::exception();
26
133
    }
27
1.35k
}
28
29
1.21k
ECCKey::~ECCKey() {
30
1.21k
    CF_NORET(wc_ecc_key_free(key));
31
1.21k
}
32
33
4.09k
ecc_key* ECCKey::GetPtr(void) {
34
4.09k
    uint8_t* x963 = nullptr;
35
4.09k
    ecc_key* newKey = nullptr;
36
37
4.09k
    bool exportToX963 = false;
38
4.09k
    try {
39
4.09k
        exportToX963 = ds.Get<bool>();
40
4.09k
    } catch ( ... ) { }
41
42
4.09k
    if ( exportToX963 == true ) {
43
422
        CF_CHECK_NE(newKey = wc_ecc_key_new(nullptr), nullptr);
44
45
323
        word32 outLen = 0;
46
47
323
        bool compressed = false;
48
323
        try { compressed  = ds.Get<bool>();} catch ( ... ) { }
49
50
590
        WC_CHECK_EQ(wc_ecc_export_x963_ex(key, nullptr, &outLen, compressed), LENGTH_ONLY_E);
51
590
        x963 = util::malloc(outLen);
52
590
        WC_CHECK_EQ(wc_ecc_export_x963_ex(key, x963, &outLen, compressed), 0);;
53
54
        /* Get the curve id of the old key */
55
127
        int curveID;
56
127
        CF_CHECK_NE(curveID = wc_ecc_get_curve_id(key->idx), ECC_CURVE_INVALID);
57
58
127
        const bool valid = wc_ecc_check_key(key) == 0;
59
60
127
        haveAllocFailure = false;
61
127
        if ( wc_ecc_import_x963_ex(x963, outLen, newKey, curveID) != 0 ) {
62
            /* Allowed to fail if either:
63
             *
64
             * - Compression is used and the input key is invalid
65
             * - An allocation failure occured during wc_ecc_import_x963_ex
66
             */
67
57
            CF_ASSERT((compressed && !valid) || haveAllocFailure, "Cannot import X963-exported ECC key");
68
57
            goto end;
69
57
        }
70
71
70
        if ( compressed ) {
72
44
            CF_CHECK_TRUE(valid);
73
19
        }
74
75
45
        CF_NORET(wc_ecc_key_free(key));
76
45
        key = newKey;
77
45
        newKey = nullptr;
78
45
    }
79
80
4.09k
end:
81
4.09k
    util::free(x963);
82
4.09k
    CF_NORET(wc_ecc_key_free(newKey));
83
84
4.09k
    return key;
85
4.09k
}
86
87
771
bool ECCKey::SetCurve(const Type& curveType) {
88
771
    bool ret = false;
89
90
771
#if !defined(WOLFSSL_SP_MATH)
91
771
    bool useCustomCurve = false;
92
93
771
    try {
94
771
        useCustomCurve = ds.Get<uint8_t>();
95
771
    } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
96
771
    useCustomCurve = false;
97
98
771
    if ( useCustomCurve == false )
99
771
#endif
100
771
    {
101
#if defined(CRYPTOFUZZ_WOLFCRYPT_DEBUG)
102
        std::cout << "Using native curve" << std::endl;
103
#endif
104
771
        std::optional<int> curveID;
105
106
771
        CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(curveType), std::nullopt);
107
744
        this->curveID = *curveID;
108
109
744
        WC_CHECK_EQ(wc_ecc_set_curve(GetPtr(), 0, *curveID), 0);
110
723
    }
111
0
#if !defined(WOLFSSL_SP_MATH)
112
0
    else {
113
 #if defined(CRYPTOFUZZ_WOLFCRYPT_DEBUG)
114
        std::cout << "Using custom curve" << std::endl;
115
 #endif
116
0
        const ecc_set_type* curveSpec;
117
0
        CF_CHECK_NE(curveSpec = GetCustomCurve(curveType.Get()), nullptr);
118
0
        WC_CHECK_EQ(wc_ecc_set_custom_curve(GetPtr(), curveSpec), 0);
119
0
        this->curveID = ECC_CURVE_CUSTOM;
120
0
    }
121
723
#endif
122
123
723
    ret = true;
124
125
771
end:
126
771
    return ret;
127
723
}
128
129
723
bool ECCKey::LoadPrivateKey(const component::Bignum& priv) {
130
723
    bool ret = false;
131
723
    std::optional<std::vector<uint8_t>> priv_bytes;
132
133
723
    CF_CHECK_NE(priv_bytes = wolfCrypt_bignum::Bignum::ToBin(ds, priv), std::nullopt);
134
135
704
    WC_CHECK_EQ(wc_ecc_import_private_key_ex(priv_bytes->data(), priv_bytes->size(), nullptr, 0, GetPtr(), *curveID), 0);
136
137
621
    ret = true;
138
139
723
end:
140
723
    return ret;
141
621
}
142
143
585
std::optional<ECCPoint> ECCKey::MakePub(void) {
144
585
    std::optional<ECCPoint> ret = std::nullopt;
145
146
585
    ECCPoint pub(ds, *curveID);
147
585
    WC_CHECK_EQ(wc_ecc_make_pub(GetPtr(), pub.GetPtr()), 0);
148
543
    pub.SetInitialized();
149
150
543
    return pub;
151
152
42
end:
153
42
    return ret;
154
585
}
155
156
21
bool ECCKey::SetRNG(void) {
157
21
    bool ret = false;
158
159
21
    WC_CHECK_EQ(wc_ecc_set_rng(GetPtr(), wolfCrypt_detail::GetRNG()), 0);
160
161
21
    ret = true;
162
21
end:
163
21
    return ret;
164
21
}
165
166
ECCPoint::ECCPoint(Datasource& ds, const int curveID) :
167
    ds(ds),
168
1.78k
    curveID(curveID) {
169
1.78k
    if ( (point = wc_ecc_new_point_h(nullptr)) == nullptr ) {
170
141
        throw std::exception();
171
141
    }
172
1.78k
}
173
174
/* Copy constructor */
175
ECCPoint::ECCPoint(const ECCPoint& other) :
176
    ds(other.ds),
177
    curveID(other.curveID),
178
    locked(other.locked),
179
    initialized(other.initialized)
180
541
{
181
541
    if ( (point = wc_ecc_new_point_h(nullptr)) == nullptr ) {
182
0
        throw std::exception();
183
0
    }
184
185
541
    if ( wc_ecc_copy_point(other.point, point) != 0 ) {
186
0
        CF_NORET(wc_ecc_del_point(point));
187
0
        throw std::exception();
188
0
    }
189
541
}
190
191
2.18k
ECCPoint::~ECCPoint() {
192
2.18k
    CF_NORET(wc_ecc_del_point(point));
193
2.18k
}
194
195
3.01k
ecc_point* ECCPoint::GetPtr() {
196
3.01k
    uint8_t* out = nullptr;
197
3.01k
    ecc_point* newPoint = nullptr;
198
199
3.01k
    if ( locked == false && initialized == true ) {
200
771
        bool exportToDER = false;
201
202
771
        try {
203
771
            exportToDER = ds.Get<bool>();
204
771
        } catch ( ... ) { }
205
206
771
        if ( exportToDER == true ) {
207
38
            bool compressed = false;
208
38
            try {
209
38
                compressed = ds.Get<bool>();
210
38
            } catch ( ... ) { }
211
212
38
            const int curveIdx = wc_ecc_get_curve_idx(curveID);
213
38
            CF_CHECK_NE(newPoint = wc_ecc_new_point_h(nullptr), nullptr);
214
215
32
            word32 outSz = 0xFFFF;
216
32
            try { outSz = ds.Get<word32>() & 0xFFFF; } catch ( ... ) { }
217
218
32
            out = util::malloc(outSz);
219
220
32
            if ( compressed == false ) {
221
20
                WC_CHECK_EQ(wc_ecc_export_point_der(curveIdx, point, out, &outSz), 0);
222
12
            } else {
223
12
                WC_CHECK_EQ(wc_ecc_export_point_der(curveIdx, point, out, &outSz), 0);
224
                //WC_CHECK_EQ(wc_ecc_export_point_der_compressed(curveIdx, point, out, &outSz), 0);
225
7
            }
226
227
17
            {
228
17
                haveAllocFailure = false;
229
17
                const bool success = wc_ecc_import_point_der(out, outSz, curveIdx, newPoint) == 0;
230
231
17
                if ( success ) {
232
                    /* Point imported. Replace old point with new point. */
233
234
17
                    CF_NORET(wc_ecc_del_point(point));
235
17
                    point = newPoint;
236
17
                    newPoint = nullptr;
237
17
                } else {
238
                    /* Failure */
239
240
0
                    if ( haveAllocFailure == false ) {
241
                        /* Failure is only acceptable if an allocation failure occured, crash otherwise */
242
0
                        CF_ASSERT(0, "Cannot import DER-exported ECC point");
243
0
                    }
244
0
                }
245
17
            }
246
17
        }
247
771
    }
248
249
3.01k
end:
250
3.01k
    util::free(out);
251
3.01k
    CF_NORET(wc_ecc_del_point(newPoint));
252
253
3.01k
    return point;
254
3.01k
}
255
256
549
bool ECCPoint::Set(const component::BignumPair& xy, const uint64_t curveType, const bool pointCheck) {
257
549
    bool ret = false;
258
259
549
    bool projective = false;
260
549
    try {
261
549
        projective = ds.Get<bool>();
262
549
    } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
263
264
549
    wolfCrypt_bignum::Bignum x(ds), y(ds), z(ds);
265
266
549
    if ( projective == false ) {
267
413
        CF_CHECK_TRUE(x.Set(xy.first));
268
411
        CF_CHECK_TRUE(y.Set(xy.second));
269
409
        CF_CHECK_TRUE(z.Set("1"));
270
409
    } else {
271
136
        const auto proj = util::ToRandomProjective(
272
136
                ds,
273
136
                xy.first.ToTrimmedString(),
274
136
                xy.second.ToTrimmedString(),
275
136
                curveType);
276
136
        CF_CHECK_TRUE(x.Set(proj[0]));
277
134
        CF_CHECK_TRUE(y.Set(proj[1]));
278
133
        CF_CHECK_TRUE(z.Set(proj[2]));
279
132
    }
280
281
1.08k
    WC_CHECK_EQ(mp_copy(x.GetPtr(), point->x), MP_OKAY);
282
1.08k
    WC_CHECK_EQ(mp_copy(y.GetPtr(), point->y), MP_OKAY);
283
541
    WC_CHECK_EQ(mp_copy(z.GetPtr(), point->z), MP_OKAY);
284
285
541
    if ( pointCheck ) {
286
0
        CF_CHECK_TRUE(CurveCheck());
287
0
    }
288
289
541
    SetInitialized();
290
291
541
    ret = true;
292
293
549
end:
294
549
    return ret;
295
541
}
296
297
319
bool ECCPoint::ToProjective(wolfCrypt_bignum::Bignum& prime) {
298
319
    bool ret = false;
299
300
319
    wolfCrypt_bignum::Bignum mu(ds);
301
302
319
    WC_CHECK_EQ(mp_montgomery_calc_normalization(mu.GetPtr(), prime.GetPtr()), MP_OKAY);
303
304
317
    if ( mp_cmp_d(mu.GetPtr(), 1) != MP_EQ ) {
305
239
        WC_CHECK_EQ(mp_mulmod(point->x, mu.GetPtr(), prime.GetPtr(), point->x), MP_OKAY);
306
230
        WC_CHECK_EQ(mp_mulmod(point->y, mu.GetPtr(), prime.GetPtr(), point->y), MP_OKAY);
307
228
        WC_CHECK_EQ(mp_mulmod(point->z, mu.GetPtr(), prime.GetPtr(), point->z), MP_OKAY);
308
227
    }
309
310
    /* Lock so it isn't attempted to export/import the projective point in GetPtr(),
311
     * which will lead to incorrect results
312
     */
313
305
    Lock();
314
315
305
    ret = true;
316
317
319
end:
318
319
    return ret;
319
305
}
320
321
495
bool ECCPoint::CurveCheck(void) const {
322
495
    const int curveIdx = wc_ecc_get_curve_idx(curveID);
323
495
    return wc_ecc_point_is_on_curve(point, curveIdx) == 0;
324
495
}
325
326
1.07k
void ECCPoint::Lock(void) {
327
1.07k
    locked = true;
328
1.07k
}
329
330
1.08k
void ECCPoint::SetInitialized(void) {
331
1.08k
    initialized = true;
332
1.08k
}
333
334
531
std::optional<component::BignumPair> ECCPoint::ToBignumPair(void) {
335
531
    std::optional<component::BignumPair> ret = std::nullopt;
336
337
531
    wolfCrypt_bignum::Bignum pub_x(GetPtr()->x, ds);
338
339
    /* Pointer is stored in pub_x; lock to prevent UAF */
340
531
    Lock();
341
342
531
    wolfCrypt_bignum::Bignum pub_y(GetPtr()->y, ds);
343
344
531
    std::optional<std::string> pub_x_str, pub_y_str;
345
531
    CF_CHECK_NE(pub_x_str = pub_x.ToDecString(), std::nullopt);
346
531
    CF_CHECK_NE(pub_y_str = pub_y.ToDecString(), std::nullopt);
347
348
530
    ret = { *pub_x_str, *pub_y_str };
349
531
end:
350
351
531
    return ret;
352
530
}
353
354
60
int ECCPoint::Compare(ECCPoint& other) {
355
60
    return wc_ecc_cmp_point(GetPtr(), other.GetPtr());
356
60
}
357
358
66
std::optional<bool> ECCPoint::IsNeg(ECCPoint& other, wolfCrypt_bignum::Bignum& prime) {
359
66
    std::optional<bool> ret = std::nullopt;
360
361
66
    wolfCrypt_bignum::Bignum neg(ds);
362
66
    if ( mp_sub(prime.GetPtr(), other.GetPtr()->y, neg.GetPtr()) == MP_OKAY) {
363
64
        ret = static_cast<bool>(mp_cmp(point->y, neg.GetPtr()) == MP_EQ);
364
64
    }
365
366
66
    return ret;
367
66
}
368
369
380
std::optional<component::ECC_PublicKey> OpECC_PrivateToPublic_Generic(operation::ECC_PrivateToPublic& op) {
370
380
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
371
380
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
372
380
    wolfCrypt_detail::SetGlobalDs(&ds);
373
374
380
    try {
375
380
        ECCKey key(ds);
376
377
        /* Initialize */
378
380
        {
379
380
            CF_CHECK_EQ(key.SetCurve(op.curveType), true);
380
361
            CF_CHECK_EQ(key.LoadPrivateKey(op.priv), true);
381
288
        }
382
383
        /* Process/Finalize */
384
0
        {
385
288
            auto pub = key.MakePub();
386
288
            CF_CHECK_NE(pub, std::nullopt);
387
388
260
            ret = pub->ToBignumPair();
389
260
        }
390
260
    } catch ( ... ) { }
391
392
380
end:
393
394
380
    wolfCrypt_detail::UnsetGlobalDs();
395
380
    return ret;
396
380
}
397
398
0
std::optional<bool> OpECC_ValidatePubkey_Generic(operation::ECC_ValidatePubkey& op) {
399
0
    std::optional<bool> ret = std::nullopt;
400
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
401
0
    wolfCrypt_detail::SetGlobalDs(&ds);
402
403
0
    std::optional<int> curveID;
404
405
0
    try {
406
0
        ECCKey key(ds);
407
0
        {
408
0
            const char* name = nullptr;
409
410
0
            CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
411
412
0
            CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr);
413
414
0
            WC_CHECK_EQ(wc_ecc_import_raw(
415
0
                        key.GetPtr(),
416
0
                        util::DecToHex(op.pub.first.ToTrimmedString()).c_str(),
417
0
                        util::DecToHex(op.pub.second.ToTrimmedString()).c_str(),
418
0
                        nullptr,
419
0
                        name), 0);
420
0
            haveAllocFailure = false;
421
0
            ret = wc_ecc_check_key(key.GetPtr()) == 0;
422
0
            if ( *ret == false && haveAllocFailure == true ) {
423
0
                ret = std::nullopt;
424
0
            }
425
0
        }
426
0
    } catch ( ... ) { }
427
428
0
end:
429
430
0
    wolfCrypt_detail::UnsetGlobalDs();
431
0
    return ret;
432
0
}
433
434
449
std::optional<bool> OpECDSA_Verify_Generic(operation::ECDSA_Verify& op) {
435
449
    std::optional<bool> ret = std::nullopt;
436
449
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
437
449
    wolfCrypt_detail::SetGlobalDs(&ds);
438
439
449
    std::optional<int> curveID;
440
449
    uint8_t* sig = nullptr;
441
449
    uint8_t* hash = nullptr;
442
449
    word32 sigSz = ECC_MAX_SIG_SIZE;
443
449
    int verify;
444
445
449
    bool ctIsEmpty = false;
446
449
    bool randomSigSz = false;
447
449
    bool hashNotFound = false;
448
449
449
    {
450
449
        try {
451
449
            randomSigSz = ds.Get<bool>();
452
449
            if ( randomSigSz ) {
453
131
                sigSz = ds.Get<uint8_t>();
454
131
            }
455
449
        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
456
457
449
        sig = util::malloc(sigSz);
458
449
    }
459
460
449
    try {
461
449
        ECCKey key(ds);
462
449
        {
463
449
            const char* name = nullptr;
464
465
449
            CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
466
467
448
            CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr);
468
469
439
            haveAllocFailure = false;
470
439
            ret = false;
471
472
439
            WC_CHECK_EQ(wc_ecc_import_raw(
473
434
                        key.GetPtr(),
474
434
                        util::DecToHex(op.signature.pub.first.ToTrimmedString()).c_str(),
475
434
                        util::DecToHex(op.signature.pub.second.ToTrimmedString()).c_str(),
476
434
                        nullptr,
477
434
                        name), 0);
478
434
            WC_CHECK_EQ(wc_ecc_check_key(key.GetPtr()), 0);
479
328
        }
480
481
328
        WC_CHECK_EQ(wc_ecc_rs_to_sig(
482
297
                    util::DecToHex(op.signature.signature.first.ToTrimmedString()).c_str(),
483
297
                    util::DecToHex(op.signature.signature.second.ToTrimmedString()).c_str(),
484
297
                    sig, &sigSz), 0);
485
486
297
        if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
487
51
            const auto CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
488
51
            ctIsEmpty = CT.GetSize() == 0;
489
51
            WC_CHECK_EQ(wc_ecc_verify_hash(sig, sigSz, CT.GetPtr(), CT.GetSize(), &verify, key.GetPtr()), 0);
490
246
        } else {
491
246
            std::optional<wc_HashType> hashType;
492
246
            hashNotFound = true;
493
246
            CF_CHECK_NE(hashType = wolfCrypt_detail::toHashType(op.digestType), std::nullopt);
494
245
            hashNotFound = false;
495
496
245
            const auto hashSize = wc_HashGetDigestSize(*hashType);
497
245
            hash = util::malloc(hashSize);
498
499
245
            WC_CHECK_EQ(wc_Hash(*hashType, op.cleartext.GetPtr(), op.cleartext.GetSize(), hash, hashSize), 0);
500
501
245
            const auto CT = Buffer(hash, hashSize).ECDSA_RandomPad(ds, op.curveType);
502
245
            ctIsEmpty = CT.GetSize() == 0;
503
245
            WC_CHECK_EQ(wc_ecc_verify_hash(sig, sigSz, CT.GetPtr(), CT.GetSize(), &verify, key.GetPtr()), 0);
504
241
        }
505
506
286
        ret = verify ? true : false;
507
286
    } catch ( ... ) { }
508
509
449
end:
510
511
449
    util::free(sig);
512
449
    util::free(hash);
513
514
449
    wolfCrypt_detail::UnsetGlobalDs();
515
516
449
    if ( ret && *ret == false ) {
517
182
        if ( haveAllocFailure ) {
518
93
            ret = std::nullopt;
519
93
        } else if ( randomSigSz ) {
520
29
            ret = std::nullopt;
521
60
        } else if ( ctIsEmpty ) {
522
            /* wolfCrypt ECDSA verification will fail if the input msg is empty */
523
4
            ret = std::nullopt;
524
56
        } else if ( hashNotFound ) {
525
1
            ret = std::nullopt;
526
55
        } else if ( op.digestType.Is(CF_DIGEST("NULL")) && op.cleartext.IsZero() ) {
527
0
            ret = std::nullopt;
528
0
        }
529
182
    }
530
531
449
    return ret;
532
449
}
533
534
0
std::optional<component::ECCSI_Signature> OpECCSI_Sign(operation::ECCSI_Sign& op) {
535
0
#if !defined(WOLFCRYPT_HAVE_ECCSI)
536
0
    (void)op;
537
0
    return std::nullopt;
538
#else
539
    std::optional<component::ECCSI_Signature> ret = std::nullopt;
540
541
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
542
    wolfCrypt_detail::SetGlobalDs(&ds);
543
544
    uint8_t hashSz = WC_MAX_DIGEST_SIZE;
545
    static_assert(WC_MAX_DIGEST_SIZE < 256);
546
547
    uint8_t* hash = util::malloc(hashSz);
548
549
    uint8_t* encoded = nullptr;
550
    EccsiKey eccsi;
551
    bool eccsi_initialized = false;
552
553
    try {
554
        int size;
555
        std::optional<component::BignumPair> pubbn = std::nullopt;
556
557
        {
558
            /* Private to public */
559
            ECCKey key(ds);
560
            CF_CHECK_EQ(key.SetCurve(op.curveType), true);
561
            CF_CHECK_GT(size = key.GetPtr()->dp->size, 0);
562
            CF_CHECK_EQ(key.LoadPrivateKey(op.priv), true);
563
            auto pub = key.MakePub();
564
            CF_CHECK_NE(pub, std::nullopt);
565
            CF_CHECK_NE(pubbn = pub->ToBignumPair(), std::nullopt);
566
567
            /* Encode private and public */
568
            encoded = util::malloc(size * 3);
569
570
            WC_CHECK_EQ(mp_to_unsigned_bin_len(&(key.GetPtr()->k), encoded, size), 0);
571
            WC_CHECK_EQ(mp_to_unsigned_bin_len(pub->GetPtr()->x, encoded + size, size), 0);
572
            WC_CHECK_EQ(mp_to_unsigned_bin_len(pub->GetPtr()->y, encoded + (size * 2), size), 0);
573
        }
574
575
        {
576
            std::optional<int> curveId;
577
            CF_CHECK_NE(curveId = toCurveID(op.curveType), std::nullopt);
578
579
            WC_CHECK_EQ(wc_InitEccsiKey_ex(&eccsi, size, *curveId, nullptr, -1), 0);
580
            eccsi_initialized = true;
581
582
            WC_CHECK_EQ(wc_ImportEccsiKey(&eccsi, encoded, size * 3), 0);
583
            {
584
                uint8_t sig[257]; /* XXX random size */
585
                word32 sigSz = sizeof(sig);
586
                ECCPoint pvt(ds, *curveId);
587
                wolfCrypt_bignum::Bignum ssk(ds);
588
                std::optional<wc_HashType> hashType;
589
                CF_CHECK_NE(hashType = toHashType(op.digestType), std::nullopt);
590
                WC_CHECK_EQ(wc_MakeEccsiPair(
591
                            &eccsi,
592
                            &rng,
593
                            *hashType,
594
                            op.id.GetPtr(),
595
                            op.id.GetSize(),
596
                            ssk.GetPtr(),
597
                            pvt.GetPtr()), 0);
598
                WC_CHECK_EQ(wc_HashEccsiId(
599
                            &eccsi,
600
                            *hashType,
601
                            op.id.GetPtr(),
602
                            op.id.GetSize(),
603
                            pvt.GetPtr(),
604
                            hash,
605
                            &hashSz), 0);
606
                WC_CHECK_EQ(wc_SetEccsiHash(&eccsi, hash, hashSz), 0);
607
                WC_CHECK_EQ(wc_SetEccsiPair(&eccsi, ssk.GetPtr(), pvt.GetPtr()), 0);
608
                WC_CHECK_EQ(wc_SignEccsiHash(
609
                            &eccsi,
610
                            &rng,
611
                            *hashType,
612
                            op.cleartext.GetPtr(),
613
                            op.cleartext.GetSize(),
614
                            sig, &sigSz), 0);
615
                CF_ASSERT(sigSz == static_cast<size_t>(size) * 4 + 1, "Unexpected signature size");
616
                {
617
                    wolfCrypt_bignum::Bignum r(ds), s(ds);
618
                    std::optional<std::string> r_str, s_str;
619
                    std::optional<component::BignumPair> pvtbn = std::nullopt;
620
621
                    WC_CHECK_EQ(mp_read_unsigned_bin(r.GetPtr(), sig, size), 0);
622
                    CF_CHECK_NE(r_str = r.ToDecString(), std::nullopt);
623
624
                    WC_CHECK_EQ(mp_read_unsigned_bin(s.GetPtr(), sig + size, size), 0);
625
                    CF_CHECK_NE(s_str = s.ToDecString(), std::nullopt);
626
627
                    CF_CHECK_NE(pvtbn = pvt.ToBignumPair(), std::nullopt);
628
629
                    ret = component::ECCSI_Signature{
630
                        component::BignumPair{*r_str, *s_str},
631
                        *pubbn,
632
                        *pvtbn};
633
                }
634
            }
635
        }
636
    } catch ( ... ) { }
637
638
end:
639
    if ( eccsi_initialized ) {
640
        CF_NORET(wc_FreeEccsiKey(&eccsi));
641
    }
642
    util::free(hash);
643
    util::free(encoded);
644
    wolfCrypt_detail::UnsetGlobalDs();
645
    return ret;
646
#endif
647
0
}
648
649
0
std::optional<bool> OpECCSI_Verify(operation::ECCSI_Verify& op) {
650
0
#if !defined(WOLFCRYPT_HAVE_ECCSI)
651
0
    (void)op;
652
0
    return std::nullopt;
653
#else
654
    std::optional<bool> ret = std::nullopt;
655
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
656
    wolfCrypt_detail::SetGlobalDs(&ds);
657
658
    uint8_t hashSz = WC_MAX_DIGEST_SIZE;
659
    static_assert(WC_MAX_DIGEST_SIZE < 256);
660
661
    EccsiKey eccsi;
662
663
    uint8_t* hash = util::malloc(hashSz);
664
    std::optional<wc_HashType> hashType;
665
    std::optional<int> curveId;
666
    std::vector<uint8_t> pub, sig;
667
    int verified;
668
    int size;
669
    bool eccsi_initialized = false;
670
671
    CF_CHECK_NE(curveId = toCurveID(op.curveType), std::nullopt);
672
    CF_CHECK_NE(hashType = toHashType(op.digestType), std::nullopt);
673
674
    haveAllocFailure = false;
675
    ret = false;
676
677
    try {
678
    {
679
        ECCKey key(ds);
680
        CF_CHECK_EQ(key.SetCurve(op.curveType), true);
681
        CF_CHECK_GT(size = key.GetPtr()->dp->size, 0);
682
    }
683
684
    /* Pub to binary */
685
    {
686
        const auto x = op.signature.pub.first.ToBin(size);
687
        CF_CHECK_NE(x, std::nullopt);
688
        pub.insert(pub.end(), x->begin(), x->end());
689
690
        const auto y = op.signature.pub.second.ToBin(size);
691
        CF_CHECK_NE(y, std::nullopt);
692
        pub.insert(pub.end(), y->begin(), y->end());
693
    }
694
695
    /* Sig to binary */
696
    {
697
        const auto r = op.signature.signature.first.ToBin(size);
698
        CF_CHECK_NE(r, std::nullopt);
699
        sig.insert(sig.end(), r->begin(), r->end());
700
701
        const auto s = op.signature.signature.second.ToBin(size);
702
        CF_CHECK_NE(s, std::nullopt);
703
        sig.insert(sig.end(), s->begin(), s->end());
704
705
        sig.push_back(0x04);
706
707
        const auto pvt_x = op.signature.pvt.first.ToBin(size);
708
        CF_CHECK_NE(pvt_x, std::nullopt);
709
        sig.insert(sig.end(), pvt_x->begin(), pvt_x->end());
710
711
        const auto pvt_y = op.signature.pvt.second.ToBin(size);
712
        CF_CHECK_NE(pvt_y, std::nullopt);
713
        sig.insert(sig.end(), pvt_y->begin(), pvt_y->end());
714
    }
715
716
    {
717
        ECCPoint pvt(ds, *curveId);
718
        CF_CHECK_TRUE(pvt.Set(op.signature.pvt, op.curveType.Get()));
719
720
        WC_CHECK_EQ(wc_InitEccsiKey_ex(&eccsi, size, *curveId, nullptr, -1), 0);
721
        eccsi_initialized = true;
722
723
        WC_CHECK_EQ(wc_ImportEccsiPublicKey(&eccsi,
724
                    pub.data(), pub.size(), 0), 0);
725
        WC_CHECK_EQ(wc_HashEccsiId(
726
                    &eccsi,
727
                    *hashType,
728
                    op.id.GetPtr(&ds), op.id.GetSize(),
729
                    pvt.GetPtr(),
730
                    hash,
731
                    &hashSz), 0);
732
        WC_CHECK_EQ(wc_SetEccsiHash(&eccsi, hash, hashSz), 0);
733
        WC_CHECK_EQ(wc_VerifyEccsiHash(
734
                    &eccsi,
735
                    *hashType,
736
                    op.cleartext.GetPtr(&ds), op.cleartext.GetSize(),
737
                    sig.data(), sig.size(),
738
                    &verified), 0);
739
        ret = verified == 1;
740
    }
741
    } catch ( ... ) { }
742
743
end:
744
    if ( eccsi_initialized ) {
745
        CF_NORET(wc_FreeEccsiKey(&eccsi));
746
    }
747
    util::free(hash);
748
    wolfCrypt_detail::UnsetGlobalDs();
749
    if ( ret && *ret == false ) {
750
        if ( haveAllocFailure ) {
751
            ret = std::nullopt;
752
        }
753
    }
754
    return ret;
755
#endif
756
0
}
757
758
519
std::optional<component::ECDSA_Signature> OpECDSA_Sign_Generic(operation::ECDSA_Sign& op) {
759
519
    std::optional<component::ECDSA_Signature> ret = std::nullopt;
760
519
    if ( op.UseRandomNonce() == false && op.UseSpecifiedNonce() == false ) {
761
116
        return ret;
762
116
    }
763
764
403
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
765
403
    wolfCrypt_detail::SetGlobalDs(&ds);
766
767
403
    uint8_t* sig = nullptr;
768
403
    word32 sigSz = ECC_MAX_SIG_SIZE;
769
403
    Buffer CT;
770
403
    uint8_t* hash = nullptr;
771
403
    size_t hashSize = 0;
772
403
    uint8_t* nonce_bytes = nullptr;
773
403
    wolfCrypt_bignum::Bignum nonce(ds), r(ds), s(ds);
774
775
403
    CF_CHECK_NE(op.priv.ToTrimmedString(), "0");
776
777
397
    {
778
397
        try {
779
397
            sigSz = ds.Get<uint8_t>();
780
397
        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
781
782
397
        sig = util::malloc(sigSz);
783
397
    }
784
785
397
    try {
786
397
        ECCKey key(ds);
787
397
        CF_CHECK_EQ(key.SetCurve(op.curveType), true);
788
388
        CF_CHECK_EQ(key.LoadPrivateKey(op.priv), true);
789
367
        key.GetPtr()->type = ECC_PRIVATEKEY_ONLY;
790
791
367
        if ( op.UseSpecifiedNonce() == true ) {
792
107
            CF_CHECK_EQ(nonce.Set(op.nonce.ToString(ds)), true);
793
794
106
            const size_t nonce_bytes_size = mp_unsigned_bin_size(nonce.GetPtr());
795
796
            /* Convert nonce to byte array */
797
106
            nonce_bytes = util::malloc(nonce_bytes_size);
798
106
            CF_CHECK_EQ(mp_to_unsigned_bin(nonce.GetPtr(), nonce_bytes), 0);
799
800
            /* Set nonce */
801
105
            WC_CHECK_EQ(wc_ecc_sign_set_k(nonce_bytes, nonce_bytes_size, key.GetPtr()), 0);
802
92
        }
803
804
352
        auto pub = key.MakePub();
805
352
        CF_CHECK_NE(pub, std::nullopt);
806
807
338
        if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
808
38
            CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
809
300
        } else {
810
300
            std::optional<wc_HashType> hashType;
811
300
            CF_CHECK_NE(hashType = wolfCrypt_detail::toHashType(op.digestType), std::nullopt);
812
813
289
            hashSize = wc_HashGetDigestSize(*hashType);
814
289
            hash = util::malloc(hashSize);
815
816
289
            WC_CHECK_EQ(wc_Hash(*hashType, op.cleartext.GetPtr(), op.cleartext.GetSize(), hash, hashSize), 0);
817
818
288
            CT = Buffer(hash, hashSize).ECDSA_RandomPad(ds, op.curveType);
819
288
        }
820
821
        /* Sign */
822
625
        WC_CHECK_EQ(wc_ecc_sign_hash(CT.GetPtr(), CT.GetSize(), sig, &sigSz, wolfCrypt_detail::GetRNG(), key.GetPtr()), 0);
823
824
        /* Verify */
825
625
        {
826
625
            int verify;
827
625
            haveAllocFailure = false;
828
625
            if ( wc_ecc_verify_hash(sig, sigSz, CT.GetPtr(), CT.GetSize(), &verify, key.GetPtr()) == 0 && haveAllocFailure == false ) {
829
264
                CF_ASSERT(verify, "Cannot verify generated signature");
830
264
            }
831
625
        }
832
833
299
        CF_CHECK_EQ(DecodeECC_DSA_Sig(sig, sigSz, r.GetPtr(), s.GetPtr()), 0);
834
299
        {
835
299
            std::optional<std::string> r_str, s_str;
836
837
299
            if ( op.curveType.Get() == CF_ECC_CURVE("secp256k1") ) {
838
51
                wolfCrypt_bignum::Bignum SMax(ds);
839
51
                CF_CHECK_EQ(SMax.Set("57896044618658097711785492504343953926418782139537452191302581570759080747168"), true);
840
51
                if ( mp_cmp(s.GetPtr(), SMax.GetPtr()) == 1 ) {
841
24
                    wolfCrypt_bignum::Bignum SSub(ds);
842
24
                    CF_CHECK_EQ(SSub.Set("115792089237316195423570985008687907852837564279074904382605163141518161494337"), true);
843
24
                    CF_CHECK_EQ(mp_sub(SSub.GetPtr(), s.GetPtr(), s.GetPtr()), 0);
844
24
                }
845
248
            } else if ( op.curveType.Get() == CF_ECC_CURVE("secp256r1") ) {
846
35
                wolfCrypt_bignum::Bignum SMax(ds);
847
35
                CF_CHECK_EQ(SMax.Set("57896044605178124381348723474703786764998477612067880171211129530534256022184"), true);
848
35
                if ( mp_cmp(s.GetPtr(), SMax.GetPtr()) == 1 ) {
849
20
                    wolfCrypt_bignum::Bignum SSub(ds);
850
20
                    CF_CHECK_EQ(SSub.Set("115792089210356248762697446949407573529996955224135760342422259061068512044369"), true);
851
20
                    CF_CHECK_EQ(mp_sub(SSub.GetPtr(), s.GetPtr(), s.GetPtr()), 0);
852
20
                }
853
35
            }
854
855
299
            CF_CHECK_NE(r_str = r.ToDecString(), std::nullopt);
856
299
            CF_CHECK_NE(s_str = s.ToDecString(), std::nullopt);
857
858
299
            const auto pub2 = pub->ToBignumPair();
859
299
            CF_CHECK_NE(pub2, std::nullopt);
860
861
299
            ret = component::ECDSA_Signature({*r_str, *s_str}, *pub2);
862
299
        }
863
299
    } catch ( ... ) { }
864
403
end:
865
866
403
    util::free(sig);
867
403
    util::free(hash);
868
403
    util::free(nonce_bytes);
869
870
403
    wolfCrypt_detail::UnsetGlobalDs();
871
872
403
    return ret;
873
397
}
874
875
0
std::optional<component::Ciphertext> OpECIES_Encrypt_Generic(operation::ECIES_Encrypt& op) {
876
0
    std::optional<component::Ciphertext> ret = std::nullopt;
877
#if !defined(HAVE_ECC_ENCRYPT)
878
    (void)op;
879
#else
880
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
881
0
    wolfCrypt_detail::SetGlobalDs(&ds);
882
0
    uint8_t* out = nullptr;
883
884
0
    CF_CHECK_TRUE(op.cipherType.Is(CF_CIPHER("AES_128_CBC")));
885
0
    CF_CHECK_EQ(op.iv, std::nullopt);
886
887
0
    try {
888
0
        ECCKey priv(ds), pub(ds);
889
0
        word32 outSz = ds.Get<uint32_t>() % 0xFFFFFF;
890
891
        /* Initialize private key */
892
0
        {
893
0
            CF_CHECK_TRUE(priv.SetCurve(op.curveType));
894
0
            CF_CHECK_TRUE(priv.LoadPrivateKey(op.priv));
895
0
            CF_CHECK_TRUE(priv.SetRNG());
896
0
        }
897
898
        /* Initialize public key */
899
0
        {
900
0
            std::optional<int> curveID;
901
0
            const char* name = nullptr;
902
903
0
            CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
904
905
0
            CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr);
906
907
0
            WC_CHECK_EQ(wc_ecc_import_raw(
908
0
                        pub.GetPtr(),
909
0
                        util::DecToHex(op.pub.first.ToTrimmedString()).c_str(),
910
0
                        util::DecToHex(op.pub.second.ToTrimmedString()).c_str(),
911
0
                        nullptr,
912
0
                        name), 0);
913
914
0
            CF_CHECK_TRUE(pub.SetRNG());
915
0
        }
916
917
0
        out = util::malloc(outSz);
918
919
0
        WC_CHECK_EQ(wc_ecc_encrypt(priv.GetPtr(), pub.GetPtr(), op.cleartext.GetPtr(), op.cleartext.GetSize(), out, &outSz, nullptr), 0);
920
921
0
        ret = component::Ciphertext(Buffer(out, outSz));
922
0
    } catch ( ... ) { }
923
924
0
end:
925
0
    util::free(out);
926
927
0
    wolfCrypt_detail::UnsetGlobalDs();
928
0
#endif
929
0
    return ret;
930
0
}
931
932
0
std::optional<component::Cleartext> OpECIES_Decrypt_Generic(operation::ECIES_Decrypt& op) {
933
0
    std::optional<component::Cleartext> ret = std::nullopt;
934
#if !defined(HAVE_ECC_ENCRYPT)
935
    (void)op;
936
#else
937
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
938
0
    wolfCrypt_detail::SetGlobalDs(&ds);
939
0
    uint8_t* out = nullptr;
940
941
0
    CF_CHECK_TRUE(op.cipherType.Is(CF_CIPHER("AES_128_CBC")));
942
0
    CF_CHECK_EQ(op.iv, std::nullopt);
943
944
0
    try {
945
0
        ECCKey priv(ds), pub(ds);
946
0
        word32 outSz = ds.Get<uint32_t>() % 0xFFFFFF;
947
948
        /* Initialize private key */
949
0
        {
950
0
            CF_CHECK_TRUE(priv.SetCurve(op.curveType));
951
0
            CF_CHECK_TRUE(priv.LoadPrivateKey(op.priv));
952
0
            CF_CHECK_TRUE(priv.SetRNG());
953
0
        }
954
955
        /* Initialize public key */
956
0
        {
957
0
            std::optional<int> curveID;
958
0
            const char* name = nullptr;
959
960
0
            CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
961
962
0
            CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr);
963
964
0
            WC_CHECK_EQ(wc_ecc_import_raw(
965
0
                        pub.GetPtr(),
966
0
                        util::DecToHex(op.pub.first.ToTrimmedString()).c_str(),
967
0
                        util::DecToHex(op.pub.second.ToTrimmedString()).c_str(),
968
0
                        nullptr,
969
0
                        name), 0);
970
971
0
            CF_CHECK_TRUE(pub.SetRNG());
972
0
        }
973
974
0
        out = util::malloc(outSz);
975
976
0
        WC_CHECK_EQ(wc_ecc_decrypt(priv.GetPtr(), pub.GetPtr(), op.ciphertext.GetPtr(), op.ciphertext.GetSize(), out, &outSz, nullptr), 0);
977
978
0
        ret = component::Cleartext(Buffer(out, outSz));
979
0
    } catch ( ... ) { }
980
981
0
end:
982
0
    util::free(out);
983
984
0
    wolfCrypt_detail::UnsetGlobalDs();
985
0
#endif
986
0
    return ret;
987
0
}
988
989
71
std::optional<component::Secret> OpECDH_Derive(operation::ECDH_Derive& op) {
990
71
    std::optional<component::Secret> ret = std::nullopt;
991
71
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
992
71
    wolfCrypt_detail::SetGlobalDs(&ds);
993
994
    /* try/catch because ECCKey constructor may throw if allocation fails */
995
71
    try {
996
        /* TODO dynamic size */
997
71
        uint8_t out[1024];
998
71
        word32 outlen = sizeof(out);
999
71
        ECCKey priv(ds), pub(ds);
1000
1001
        /* Initialize private key */
1002
71
        {
1003
71
            CF_CHECK_TRUE(priv.SetCurve(op.curveType));
1004
51
            CF_CHECK_TRUE(priv.LoadPrivateKey(op.priv));
1005
43
            CF_CHECK_TRUE(priv.SetRNG());
1006
43
        }
1007
1008
        /* Initialize public key */
1009
0
        {
1010
43
            std::optional<int> curveID;
1011
43
            const char* name = nullptr;
1012
1013
43
            CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
1014
1015
43
            CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr);
1016
1017
43
            WC_CHECK_EQ(wc_ecc_import_raw(
1018
38
                        pub.GetPtr(),
1019
38
                        util::DecToHex(op.pub.first.ToTrimmedString()).c_str(),
1020
38
                        util::DecToHex(op.pub.second.ToTrimmedString()).c_str(),
1021
38
                        nullptr,
1022
38
                        name), 0);
1023
38
            WC_CHECK_EQ(wc_ecc_check_key(pub.GetPtr()), 0);
1024
28
        }
1025
1026
28
        WC_CHECK_EQ(wc_ecc_shared_secret(priv.GetPtr(), pub.GetPtr(), out, &outlen), 0);
1027
1028
27
        ret = component::Secret(Buffer(out, outlen));
1029
27
    } catch ( ... ) { }
1030
1031
71
end:
1032
71
    wolfCrypt_detail::UnsetGlobalDs();
1033
1034
71
    return ret;
1035
71
}
1036
1037
118
std::optional<component::ECC_Point> OpECC_Point_Add(operation::ECC_Point_Add& op) {
1038
118
    std::optional<component::ECC_Point> ret = std::nullopt;
1039
118
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1040
118
    wolfCrypt_detail::SetGlobalDs(&ds);
1041
1042
118
    std::optional<int> curveID;
1043
118
    int curveIdx;
1044
118
    const ecc_set_type* curve = nullptr;
1045
1046
118
    CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
1047
1048
110
    CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID);
1049
101
    CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr);
1050
1051
    /* try/catch because ECCPoint constructor may throw if allocation fails */
1052
101
    try {
1053
101
        ECCPoint res(ds, *curveID), a(ds, *curveID), b(ds, *curveID);
1054
101
        wolfCrypt_bignum::Bignum Af(ds), prime(ds), mu(ds);
1055
101
        mp_digit mp;
1056
101
        bool valid = false;
1057
101
        std::optional<bool> is_neg = std::nullopt;
1058
1059
        /* Set points */
1060
101
        CF_CHECK_TRUE(a.Set(op.a, op.curveType.Get()));
1061
100
        CF_CHECK_TRUE(b.Set(op.b, op.curveType.Get()));
1062
1063
99
        valid = a.CurveCheck() && b.CurveCheck();
1064
1065
        /* Retrieve curve parameter */
1066
99
        CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true);
1067
98
        CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true);
1068
1069
96
        is_neg = a.IsNeg(b, prime);
1070
1071
96
        CF_CHECK_TRUE(a.ToProjective(prime));
1072
91
        CF_CHECK_TRUE(b.ToProjective(prime));
1073
1074
90
        WC_CHECK_EQ(mp_montgomery_setup(prime.GetPtr(), &mp), MP_OKAY);
1075
1076
#if defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
1077
        goto end;
1078
#else
1079
90
        {
1080
90
            bool dbl = false;
1081
90
            bool safe = false;
1082
1083
90
            if ( a.Compare(b) == MP_EQ ) {
1084
14
                try { dbl = ds.Get<bool>(); } catch ( ... ) { }
1085
14
            }
1086
1087
90
#if !(defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL))
1088
90
            try { safe = ds.Get<bool>(); } catch ( ... ) { }
1089
90
#endif
1090
1091
90
            if ( safe ) {
1092
#if defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
1093
                CF_UNREACHABLE();
1094
#else
1095
3
                int infinity;
1096
1097
3
                if ( dbl == true ) {
1098
1
                    WC_CHECK_EQ(ecc_projective_dbl_point_safe(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0);
1099
2
                } else {
1100
2
                    WC_CHECK_EQ(ecc_projective_add_point_safe(a.GetPtr(), b.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp, &infinity), 0);
1101
1
                }
1102
3
#endif
1103
57
            } else {
1104
57
                if ( dbl == true ) {
1105
3
                    WC_CHECK_EQ(ecc_projective_dbl_point(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0);
1106
54
                } else {
1107
54
                    WC_CHECK_EQ(ecc_projective_add_point(a.GetPtr(), b.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0);
1108
1109
                    /* Do not return result if inputs are negations of the same point */
1110
50
                    CF_CHECK_NE(is_neg, std::nullopt);
1111
49
                    CF_CHECK_FALSE(*is_neg);
1112
49
                }
1113
57
            }
1114
1115
            /* Lock to prevent exporting the projective point */
1116
53
            res.Lock();
1117
53
        }
1118
0
#endif
1119
1120
        /* To affine */
1121
53
        WC_CHECK_EQ(ecc_map(res.GetPtr(), prime.GetPtr(), mp), MP_OKAY);
1122
1123
        /* Only return the result if the input points are valid */
1124
52
        CF_CHECK_TRUE(valid);
1125
1126
        /* Only return the result if the output point is valid */
1127
4
        CF_CHECK_TRUE(res.CurveCheck());
1128
1129
4
        ret = res.ToBignumPair();
1130
30
    } catch ( ... ) { }
1131
1132
118
end:
1133
118
    wolfCrypt_detail::UnsetGlobalDs();
1134
1135
118
    return ret;
1136
101
}
1137
1138
309
std::optional<component::ECC_Point> OpECC_Point_Mul(operation::ECC_Point_Mul& op) {
1139
309
    std::optional<component::ECC_Point> ret = std::nullopt;
1140
309
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1141
309
    wolfCrypt_detail::SetGlobalDs(&ds);
1142
1143
309
    std::optional<int> curveID;
1144
309
    int curveIdx;
1145
309
    const ecc_set_type* curve = nullptr;
1146
1147
309
    CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
1148
1149
300
    CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID);
1150
278
    CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr);
1151
1152
    /* try/catch because ECCPoint constructor may throw if allocation fails */
1153
278
    try {
1154
278
        ECCPoint res(ds, *curveID), a(ds, *curveID);
1155
278
        wolfCrypt_bignum::Bignum b(ds), Af(ds), prime(ds);
1156
278
        bool valid = false;
1157
1158
        /* Set point */
1159
278
        CF_CHECK_TRUE(a.Set(op.a, op.curveType.Get()));
1160
275
        valid = a.CurveCheck();
1161
1162
        /* Set multiplier */
1163
275
        CF_CHECK_EQ(b.Set(op.b.ToString(ds)), true);
1164
1165
        /* Retrieve curve parameters */
1166
273
        CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true);
1167
272
        CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true);
1168
1169
        /* Multiply */
1170
271
        WC_CHECK_EQ(wc_ecc_mulmod_ex(b.GetPtr(), a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), 1, nullptr), 0);
1171
1172
        /* Only return the result if the input point is valid */
1173
225
        CF_CHECK_TRUE(valid);
1174
1175
83
        ret = res.ToBignumPair();
1176
83
    } catch ( ... ) { }
1177
1178
309
end:
1179
309
    wolfCrypt_detail::UnsetGlobalDs();
1180
1181
309
    return ret;
1182
278
}
1183
1184
264
std::optional<component::ECC_Point> OpECC_Point_Dbl(operation::ECC_Point_Dbl& op) {
1185
264
    std::optional<component::ECC_Point> ret = std::nullopt;
1186
264
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1187
264
    wolfCrypt_detail::SetGlobalDs(&ds);
1188
1189
264
    std::optional<int> curveID;
1190
264
    int curveIdx;
1191
264
    const ecc_set_type* curve = nullptr;
1192
1193
264
    CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
1194
1195
243
    CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID);
1196
239
    CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr);
1197
1198
    /* try/catch because ECCPoint constructor may throw if allocation fails */
1199
239
    try {
1200
239
        ECCPoint res(ds, *curveID), a(ds, *curveID);
1201
239
        wolfCrypt_bignum::Bignum Af(ds), prime(ds), mu(ds);
1202
239
        mp_digit mp;
1203
239
        bool valid = false;
1204
1205
        /* Set points */
1206
239
        CF_CHECK_TRUE(a.Set(op.a, op.curveType.Get()));
1207
1208
236
        valid = a.CurveCheck();
1209
1210
        /* Retrieve curve parameter */
1211
236
        CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true);
1212
234
        CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true);
1213
1214
233
        CF_CHECK_TRUE(a.ToProjective(prime));
1215
1216
225
        WC_CHECK_EQ(mp_montgomery_setup(prime.GetPtr(), &mp), MP_OKAY);
1217
1218
#if defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
1219
        goto end;
1220
#else
1221
225
        {
1222
225
            bool safe = false;
1223
1224
225
#if !(defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL))
1225
225
            try { safe = ds.Get<bool>(); } catch ( ... ) { }
1226
225
#endif
1227
1228
225
            if ( safe ) {
1229
#if defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
1230
                CF_UNREACHABLE();
1231
#else
1232
6
                WC_CHECK_EQ(ecc_projective_dbl_point_safe(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0);
1233
5
#endif
1234
178
            } else {
1235
178
                WC_CHECK_EQ(ecc_projective_dbl_point(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0);
1236
176
            }
1237
1238
            /* Lock to prevent exporting the projective point */
1239
181
            res.Lock();
1240
181
        }
1241
0
#endif
1242
1243
        /* To affine */
1244
181
        WC_CHECK_EQ(ecc_map(res.GetPtr(), prime.GetPtr(), mp), MP_OKAY);
1245
1246
        /* Only return the result if the input points are valid */
1247
178
        CF_CHECK_TRUE(valid);
1248
1249
        /* Only return the result if the output point is valid */
1250
11
        CF_CHECK_TRUE(res.CurveCheck());
1251
1252
10
        ret = res.ToBignumPair();
1253
41
    } catch ( ... ) { }
1254
1255
264
end:
1256
264
    wolfCrypt_detail::UnsetGlobalDs();
1257
1258
264
    return ret;
1259
239
}
1260
1261
0
std::optional<bool> OpECC_Point_Cmp(operation::ECC_Point_Cmp& op) {
1262
#if 0
1263
    std::optional<bool> ret = std::nullopt;
1264
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1265
    wolfCrypt_detail::SetGlobalDs(&ds);
1266
1267
    std::optional<int> curveID;
1268
    int curveIdx;
1269
    const ecc_set_type* curve = nullptr;
1270
1271
    CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt);
1272
1273
    CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID);
1274
    CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr);
1275
1276
    /* try/catch because ECCPoint constructor may throw if allocation fails */
1277
    try {
1278
        ECCPoint res(ds, *curveID), a(ds, *curveID), b(ds, *curveID);
1279
        wolfCrypt_bignum::Bignum Af(ds), prime(ds), mu(ds);
1280
        bool valid = false;
1281
1282
        /* Set points */
1283
        CF_CHECK_TRUE(a.Set(op.a, op.curveType.Get()));
1284
        CF_CHECK_TRUE(b.Set(op.b, op.curveType.Get()));
1285
1286
        valid = a.CurveCheck() && b.CurveCheck();
1287
        (void)valid;
1288
1289
        /* Retrieve curve parameter */
1290
        CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true);
1291
        CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true);
1292
1293
        CF_CHECK_TRUE(a.ToProjective(prime));
1294
        CF_CHECK_TRUE(b.ToProjective(prime));
1295
1296
        ret = wc_ecc_cmp_point(a.GetPtr(), b.GetPtr()) == MP_EQ;
1297
    } catch ( ... ) { }
1298
1299
end:
1300
    wolfCrypt_detail::UnsetGlobalDs();
1301
1302
    return ret;
1303
#else
1304
    /* ZD 15599 */
1305
0
    (void)op;
1306
0
    return std::nullopt;
1307
0
#endif
1308
0
}
1309
1310
} /* namespace wolfCrypt_detail */
1311
} /* namespace module */
1312
} /* namespace cryptofuzz */