Coverage Report

Created: 2025-12-31 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptofuzz-sp-math-all-8bit/modules/wolfcrypt/ecdsa_448.cpp
Line
Count
Source
1
#include "ecdsa_448.h"
2
#include "module_internal.h"
3
#include "shared.h"
4
#include "bn_ops.h"
5
#include <cryptofuzz/util.h>
6
7
extern "C" {
8
#include <wolfssl/options.h>
9
#include <wolfssl/wolfcrypt/curve448.h>
10
#include <wolfssl/wolfcrypt/ed448.h>
11
}
12
13
namespace cryptofuzz {
14
namespace module {
15
namespace wolfCrypt_detail {
16
17
#if defined(CRYPTOFUZZ_WOLFCRYPT_ALLOCATION_FAILURES)
18
    extern bool haveAllocFailure;
19
#endif
20
21
2.03k
static bool ed448LoadPrivateKey(ed448_key& key, component::Bignum priv, Datasource& ds) {
22
2.03k
    bool ret = false;
23
24
2.03k
    uint8_t priv_bytes[ED448_KEY_SIZE];
25
26
2.03k
    CF_CHECK_EQ(wolfCrypt_bignum::Bignum::ToBin(ds, priv, priv_bytes, sizeof(priv_bytes)), true);
27
1.97k
    CF_CHECK_EQ(wc_ed448_import_private_only(priv_bytes, sizeof(priv_bytes), &key), 0);
28
29
1.97k
    ret = true;
30
2.03k
end:
31
2.03k
    return ret;
32
1.97k
}
33
34
3.69k
static std::optional<std::vector<uint8_t>> ed448GetPublicKeyAsVector(ed448_key& key) {
35
3.69k
    std::optional<std::vector<uint8_t>> ret = std::nullopt;
36
3.69k
    uint8_t pub_bytes[ED448_PUB_KEY_SIZE];
37
38
3.69k
    WC_CHECK_EQ(wc_ed448_make_public(&key, pub_bytes, sizeof(pub_bytes)), MP_OKAY);
39
40
3.62k
    ret = std::vector<uint8_t>(pub_bytes, pub_bytes + sizeof(pub_bytes));
41
3.69k
end:
42
3.69k
    return ret;
43
3.62k
}
44
45
1.72k
static std::optional<component::ECC_PublicKey> ed448GetPublicKey(ed448_key& key, Datasource& ds) {
46
1.72k
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
47
1.72k
    std::optional<std::vector<uint8_t>> pubv = std::nullopt;
48
1.72k
    std::optional<component::Bignum> pub = std::nullopt;
49
50
1.72k
    CF_CHECK_NE(pubv = ed448GetPublicKeyAsVector(key), std::nullopt);
51
1.70k
    CF_CHECK_NE(pub = wolfCrypt_bignum::Bignum::BinToBignum(ds, pubv->data(), pubv->size()), std::nullopt);
52
53
1.68k
    ret = {pub->ToString(), "0"};
54
55
1.72k
end:
56
1.72k
    return ret;
57
1.68k
}
58
59
1.97k
static bool ed448DerivePublicKey(ed448_key& key) {
60
1.97k
    std::optional<std::vector<uint8_t>> pubv = std::nullopt;
61
1.97k
    bool ret = false;
62
63
1.97k
    CF_CHECK_NE(pubv = ed448GetPublicKeyAsVector(key), std::nullopt);
64
1.91k
    memcpy(key.p, pubv->data(), ED448_PUB_KEY_SIZE);
65
1.91k
    key.pubKeySet = 1;
66
67
1.91k
    ret = true;
68
69
1.97k
end:
70
1.97k
    return ret;
71
1.91k
}
72
73
2.92k
static bool ed448LoadPublicKey(ed448_key& key, component::Bignum pub, Datasource& ds, const bool mustSucceed = false) {
74
2.92k
    bool ret = false;
75
76
2.92k
    uint8_t pub_bytes[ED448_PUB_KEY_SIZE];
77
2.92k
    CF_CHECK_EQ(wolfCrypt_bignum::Bignum::ToBin(ds, pub, pub_bytes, sizeof(pub_bytes), mustSucceed), true);
78
2.85k
    CF_CHECK_EQ(wc_ed448_import_public(pub_bytes, sizeof(pub_bytes), &key), 0);
79
80
2.71k
    ret = true;
81
2.92k
end:
82
2.92k
    return ret;
83
2.71k
}
84
85
1.04k
std::optional<component::ECC_PublicKey> OpECC_PrivateToPublic_Curve448(operation::ECC_PrivateToPublic& op) {
86
1.04k
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
87
1.04k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
88
1.04k
    wolfCrypt_detail::SetGlobalDs(&ds);
89
90
1.04k
    static const uint8_t basepoint[CURVE448_KEY_SIZE] = {5};
91
92
1.04k
    std::optional<std::vector<uint8_t>> priv_bytes = std::nullopt;
93
1.04k
    uint8_t pub_bytes[CURVE448_PUB_KEY_SIZE];
94
95
    /* Load private key */
96
1.04k
    {
97
1.04k
        priv_bytes = util::DecToBin(op.priv.ToTrimmedString(), CURVE448_KEY_SIZE);
98
1.04k
        CF_CHECK_NE(priv_bytes, std::nullopt);
99
100
880
        priv_bytes->data()[0] &= 0xFC;
101
880
        priv_bytes->data()[55] |= 0x80; static_assert(55 < CURVE448_KEY_SIZE);
102
880
    }
103
104
    /* Convert to public key */
105
0
    {
106
880
        CF_CHECK_EQ(curve448(pub_bytes, priv_bytes->data(), basepoint), MP_OKAY);
107
880
    }
108
109
    /* Convert public key */
110
0
    {
111
880
        ret = { util::BinToDec(pub_bytes, sizeof(pub_bytes)), "0" };
112
880
    }
113
114
1.04k
end:
115
1.04k
    wolfCrypt_detail::UnsetGlobalDs();
116
1.04k
    return ret;
117
880
}
118
119
435
std::optional<component::ECC_PublicKey> OpECC_PrivateToPublic_Ed448(operation::ECC_PrivateToPublic& op) {
120
435
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
121
435
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
122
435
    wolfCrypt_detail::SetGlobalDs(&ds);
123
124
435
    uint8_t pub_bytes[ED448_PUB_KEY_SIZE];
125
126
435
    ed448_key key;
127
435
    bool e448_key_inited = false;
128
129
435
    WC_CHECK_EQ(wc_ed448_init(&key), 0);
130
435
    e448_key_inited = true;
131
132
    /* Load private key */
133
435
    {
134
435
        const auto priv_bytes = util::DecToBin(op.priv.ToTrimmedString(), ED448_KEY_SIZE);
135
435
        CF_CHECK_NE(priv_bytes, std::nullopt);
136
137
370
        WC_CHECK_EQ(wc_ed448_import_private_only(priv_bytes->data(), priv_bytes->size(), &key), 0);
138
370
    }
139
140
    /* Convert to public key */
141
0
    {
142
370
        WC_CHECK_EQ(wc_ed448_make_public(&key, pub_bytes, sizeof(pub_bytes)), MP_OKAY);
143
269
    }
144
145
    /* Convert public key */
146
0
    {
147
269
        ret = { util::BinToDec(pub_bytes, sizeof(pub_bytes)), "0" };
148
269
    }
149
150
435
end:
151
435
    if ( e448_key_inited == true ) {
152
435
        wc_ed448_free(&key);
153
435
    }
154
155
435
    wolfCrypt_detail::UnsetGlobalDs();
156
435
    return ret;
157
269
}
158
159
0
std::optional<bool> OpECC_ValidatePubkey_Ed448(operation::ECC_ValidatePubkey& op) {
160
0
    std::optional<bool> ret = std::nullopt;
161
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
162
0
    wolfCrypt_detail::SetGlobalDs(&ds);
163
164
0
    ed448_key key;
165
0
    bool e448_key_inited = false;
166
167
0
    WC_CHECK_EQ(wc_ed448_init(&key), 0);
168
0
    e448_key_inited = true;
169
170
0
    CF_CHECK_EQ(ed448LoadPublicKey(key, op.pub.first, ds), true);
171
172
0
    haveAllocFailure = false;
173
0
    ret = wc_ed448_check_key(&key) == 0;
174
0
    if ( *ret == false && haveAllocFailure == true ) {
175
0
        ret = std::nullopt;
176
0
    }
177
178
0
end:
179
0
    if ( e448_key_inited == true ) {
180
0
        wc_ed448_free(&key);
181
0
    }
182
183
0
    wolfCrypt_detail::UnsetGlobalDs();
184
0
    return ret;
185
0
}
186
187
0
std::optional<bool> OpECC_ValidatePubkey_Curve448(operation::ECC_ValidatePubkey& op) {
188
0
    std::optional<bool> ret = std::nullopt;
189
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
190
0
    wolfCrypt_detail::SetGlobalDs(&ds);
191
192
0
    wolfCrypt_bignum::Bignum pub(ds);
193
0
    uint8_t pub_bytes[CURVE448_KEY_SIZE];
194
195
0
    CF_CHECK_EQ(pub.Set(op.pub.first.ToString(ds)), true);
196
0
    CF_CHECK_TRUE(pub.ToBin(pub_bytes, sizeof(pub_bytes)));
197
198
0
    haveAllocFailure = false;
199
0
    ret = wc_curve448_check_public(pub_bytes, sizeof(pub_bytes), EC448_BIG_ENDIAN) == 0;
200
0
    if ( *ret == false && haveAllocFailure == true ) {
201
0
        ret = std::nullopt;
202
0
    }
203
204
0
end:
205
206
0
    wolfCrypt_detail::UnsetGlobalDs();
207
0
    return ret;
208
0
}
209
210
2.03k
std::optional<component::ECDSA_Signature> OpECDSA_Sign_ed448(operation::ECDSA_Sign& op) {
211
2.03k
    std::optional<component::ECDSA_Signature> ret = std::nullopt;
212
2.03k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
213
2.03k
    wolfCrypt_detail::SetGlobalDs(&ds);
214
215
2.03k
    ed448_key key;
216
2.03k
    bool e448_key_inited = false;
217
2.03k
    uint8_t sig[ED448_SIG_SIZE];
218
2.03k
    word32 sigSz = sizeof(sig);
219
220
2.03k
    WC_CHECK_EQ(wc_ed448_init(&key), 0);
221
2.03k
    e448_key_inited = true;
222
223
2.03k
    CF_CHECK_EQ(wolfCrypt_detail::ed448LoadPrivateKey(key, op.priv, ds), true);
224
1.97k
    CF_CHECK_EQ(wolfCrypt_detail::ed448DerivePublicKey(key), true);
225
226
    /* Sign message */
227
1.91k
    WC_CHECK_EQ(wc_ed448_sign_msg(op.cleartext.GetPtr(), op.cleartext.GetSize(), sig, &sigSz, &key, nullptr, 0), MP_OKAY);
228
1.77k
    CF_CHECK_EQ(sigSz, ED448_SIG_SIZE);
229
1.77k
    static_assert(ED448_SIG_SIZE % 2 == 0);
230
231
1.77k
    {
232
1.77k
        std::optional<component::BignumPair> ret_sig;
233
1.77k
        std::optional<component::BignumPair> ret_pub;
234
235
1.77k
        CF_CHECK_NE(ret_sig = wolfCrypt_bignum::Bignum::BinToBignumPair(ds, sig, ED448_SIG_SIZE), std::nullopt);
236
1.72k
        CF_CHECK_NE(ret_pub = wolfCrypt_detail::ed448GetPublicKey(key, ds), std::nullopt);
237
238
1.68k
        ret = component::ECDSA_Signature(*ret_sig, *ret_pub);
239
1.68k
    }
240
241
2.03k
end:
242
2.03k
    if ( e448_key_inited == true ) {
243
2.03k
        wc_ed448_free(&key);
244
2.03k
    }
245
246
2.03k
    wolfCrypt_detail::UnsetGlobalDs();
247
2.03k
    return ret;
248
1.68k
}
249
250
2.92k
std::optional<bool> OpECDSA_Verify_ed448(operation::ECDSA_Verify& op) {
251
2.92k
    std::optional<bool> ret = std::nullopt;
252
2.92k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
253
2.92k
    wolfCrypt_detail::SetGlobalDs(&ds);
254
255
2.92k
    ed448_key key;
256
2.92k
    bool e448_key_inited = false;
257
2.92k
    uint8_t ed448sig[ED448_SIG_SIZE];
258
2.92k
    int verify;
259
2.92k
    bool oneShot = true;
260
2.92k
    bool haveEmptyPart = false;
261
262
2.92k
    haveAllocFailure = false;
263
2.92k
    ret = false;
264
265
2.92k
    WC_CHECK_EQ(wc_ed448_init(&key), 0);
266
2.92k
    e448_key_inited = true;
267
268
2.92k
    CF_CHECK_EQ(ed448LoadPublicKey(key, op.signature.pub.first, ds, true), true);
269
2.71k
    CF_CHECK_EQ(wolfCrypt_bignum::Bignum::ToBin(ds, op.signature.signature, ed448sig, sizeof(ed448sig), true), true);
270
271
2.58k
#if defined(WOLFSSL_ED25519_STREAMING_VERIFY)
272
2.58k
    try { oneShot = ds.Get<bool>(); } catch ( ... ) { }
273
2.58k
#endif
274
275
2.58k
    if ( oneShot == true ) {
276
1.82k
        WC_CHECK_EQ(wc_ed448_verify_msg(ed448sig, sizeof(ed448sig), op.cleartext.GetPtr(), op.cleartext.GetSize(), &verify, &key, nullptr, 0), 0);
277
1.14k
    } else {
278
#if !defined(WOLFSSL_ED25519_STREAMING_VERIFY)
279
        CF_UNREACHABLE();
280
#else
281
752
        const auto parts = util::ToParts(ds, op.cleartext);
282
283
752
        WC_CHECK_EQ(wc_ed448_verify_msg_init(ed448sig, sizeof(ed448sig), &key, (byte)Ed448, nullptr, 0), 0);
284
285
240k
        for (const auto& part : parts) {
286
240k
            if ( part.second == 0 ) {
287
238k
                haveEmptyPart = true;
288
238k
            }
289
240k
            WC_CHECK_EQ(wc_ed448_verify_msg_update(part.first, part.second, &key), 0);
290
240k
        }
291
292
1.17k
        WC_CHECK_EQ(wc_ed448_verify_msg_final(ed448sig, sizeof(ed448sig), &verify, &key), 0);
293
1.17k
#endif
294
1.17k
    }
295
296
1.58k
    ret = verify ? true : false;
297
298
2.92k
end:
299
2.92k
    if ( e448_key_inited == true ) {
300
2.92k
        wc_ed448_free(&key);
301
2.92k
    }
302
303
2.92k
    wolfCrypt_detail::UnsetGlobalDs();
304
305
2.92k
    if ( ret && *ret == false ) {
306
1.34k
        if ( haveAllocFailure ) {
307
305
            ret = std::nullopt;
308
1.03k
        } else if ( haveEmptyPart ) {
309
167
            ret = std::nullopt;
310
871
        } else if ( op.cleartext.IsZero() ) {
311
83
            ret = std::nullopt;
312
83
        }
313
314
1.34k
    }
315
2.92k
    return ret;
316
1.58k
}
317
318
} /* namespace wolfCrypt_detail */
319
} /* namespace module */
320
} /* namespace cryptofuzz */