Coverage Report

Created: 2022-08-24 06:37

/src/cryptofuzz-normal-math/modules/wolfcrypt/ecdsa_25519.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "ecdsa_25519.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/curve25519.h>
10
#include <wolfssl/wolfcrypt/ed25519.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.77k
static bool ed25519LoadPrivateKey(ed25519_key& key, component::Bignum priv, Datasource& ds) {
22
2.77k
    bool ret = false;
23
24
2.77k
    static_assert(sizeof(key.k) == 64);
25
2.77k
    memset(key.k + 32, 0, 32);
26
2.77k
    CF_CHECK_EQ(wolfCrypt_bignum::Bignum::ToBin(ds, priv, key.k, 32), true);
27
28
2.56k
    ret = true;
29
2.77k
end:
30
2.77k
    return ret;
31
2.56k
}
32
33
4.03k
static bool ed25519LoadPublicKey(ed25519_key& key, component::Bignum pub, Datasource& ds) {
34
4.03k
    bool ret = false;
35
36
4.03k
    CF_CHECK_EQ(wolfCrypt_bignum::Bignum::ToBin(ds, pub, key.p, sizeof(key.p)), true);
37
3.86k
    key.pubKeySet = 1;
38
39
3.86k
    ret = true;
40
4.03k
end:
41
4.03k
    return ret;
42
3.86k
}
43
44
4.30k
static std::optional<std::vector<uint8_t>> ed25519GetPublicKeyAsVector(ed25519_key& key) {
45
4.30k
    std::optional<std::vector<uint8_t>> ret = std::nullopt;
46
4.30k
    uint8_t pub_bytes[ED25519_PUB_KEY_SIZE];
47
48
4.30k
    WC_CHECK_EQ(wc_ed25519_make_public(&key, pub_bytes, sizeof(pub_bytes)), MP_OKAY);
49
50
4.08k
    ret = std::vector<uint8_t>(pub_bytes, pub_bytes + sizeof(pub_bytes));
51
4.30k
end:
52
4.30k
    return ret;
53
4.08k
}
54
55
1.98k
static std::optional<component::ECC_PublicKey> ed25519GetPublicKey(ed25519_key& key, Datasource& ds) {
56
1.98k
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
57
1.98k
    std::optional<std::vector<uint8_t>> pubv = std::nullopt;
58
1.98k
    std::optional<component::Bignum> pub = std::nullopt;
59
60
1.98k
    CF_CHECK_NE(pubv = ed25519GetPublicKeyAsVector(key), std::nullopt);
61
1.89k
    CF_CHECK_NE(pub = wolfCrypt_bignum::Bignum::BinToBignum(ds, pubv->data(), pubv->size()), std::nullopt);
62
63
1.82k
    ret = {pub->ToString(), "0"};
64
65
1.98k
end:
66
1.98k
    return ret;
67
1.82k
}
68
69
2.31k
static bool ed25519DerivePublicKey(ed25519_key& key) {
70
2.31k
    std::optional<std::vector<uint8_t>> pubv = std::nullopt;
71
2.31k
    bool ret = false;
72
73
2.31k
    CF_CHECK_NE(pubv = ed25519GetPublicKeyAsVector(key), std::nullopt);
74
2.19k
    memcpy(key.p, pubv->data(), ED25519_PUB_KEY_SIZE);
75
2.19k
    key.pubKeySet = 1;
76
77
2.19k
    ret = true;
78
79
2.31k
end:
80
2.31k
    return ret;
81
2.19k
}
82
83
766
std::optional<component::ECC_PublicKey> OpECC_PrivateToPublic_Curve25519(operation::ECC_PrivateToPublic& op) {
84
766
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
85
766
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
86
766
    wolfCrypt_detail::SetGlobalDs(&ds);
87
88
766
    wolfCrypt_bignum::Bignum priv(ds), pub(ds);
89
766
    uint8_t pub_bytes[CURVE25519_KEYSIZE];
90
766
    uint8_t priv_bytes[CURVE25519_KEYSIZE];
91
92
    /* Load private key */
93
766
    {
94
766
        CF_CHECK_EQ(priv.Set(op.priv.ToString(ds)), true);
95
702
        CF_CHECK_TRUE(priv.ToBin(priv_bytes, sizeof(priv_bytes)));
96
608
        priv_bytes[0] &= 248;
97
608
        priv_bytes[31] &= 127;
98
608
        priv_bytes[31] |= 64;
99
608
    }
100
101
    /* Convert to public key */
102
0
    {
103
608
        WC_CHECK_EQ(wc_curve25519_make_pub(sizeof(pub_bytes), pub_bytes, sizeof(priv_bytes), priv_bytes), MP_OKAY);
104
608
    }
105
106
    /* Convert public key */
107
0
    {
108
608
        std::optional<std::string> pub_x_str;
109
608
        CF_CHECK_EQ(mp_read_unsigned_bin(pub.GetPtr(), pub_bytes, sizeof(pub_bytes)), MP_OKAY);
110
608
        CF_CHECK_NE(pub_x_str = pub.ToDecString(), std::nullopt);
111
566
        ret = { *pub_x_str, "0" };
112
566
    }
113
114
766
end:
115
766
    wolfCrypt_detail::UnsetGlobalDs();
116
766
    return ret;
117
566
}
118
119
400
std::optional<component::ECC_PublicKey> OpECC_PrivateToPublic_Ed25519(operation::ECC_PrivateToPublic& op) {
120
400
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
121
400
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
122
400
    wolfCrypt_detail::SetGlobalDs(&ds);
123
124
400
    wolfCrypt_bignum::Bignum priv(ds), pub(ds);
125
126
400
    ed25519_key key;
127
400
    bool e25519_key_inited = false;
128
129
400
    WC_CHECK_EQ(wc_ed25519_init(&key), 0);
130
400
    e25519_key_inited = true;
131
132
400
    CF_CHECK_EQ(ed25519LoadPrivateKey(key, op.priv, ds), true);
133
247
    ret = ed25519GetPublicKey(key, ds);
134
135
400
end:
136
400
    if ( e25519_key_inited == true ) {
137
400
        wc_ed25519_free(&key);
138
400
    }
139
140
400
    wolfCrypt_detail::UnsetGlobalDs();
141
400
    return ret;
142
247
}
143
144
551
std::optional<bool> OpECC_ValidatePubkey_Curve25519(operation::ECC_ValidatePubkey& op) {
145
551
    std::optional<bool> ret = std::nullopt;
146
551
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
147
551
    wolfCrypt_detail::SetGlobalDs(&ds);
148
149
551
    wolfCrypt_bignum::Bignum pub(ds);
150
551
    uint8_t pub_bytes[CURVE25519_KEYSIZE];
151
152
551
    CF_CHECK_EQ(pub.Set(op.pub.first.ToString(ds)), true);
153
493
    CF_CHECK_TRUE(pub.ToBin(pub_bytes, sizeof(pub_bytes)));
154
155
438
    haveAllocFailure = false;
156
438
    ret = wc_curve25519_check_public(pub_bytes, sizeof(pub_bytes), EC25519_BIG_ENDIAN) == 0;
157
438
    if ( *ret == false && haveAllocFailure == true ) {
158
0
        ret = std::nullopt;
159
0
    }
160
161
551
end:
162
163
551
    wolfCrypt_detail::UnsetGlobalDs();
164
551
    return ret;
165
438
}
166
167
398
std::optional<bool> OpECC_ValidatePubkey_Ed25519(operation::ECC_ValidatePubkey& op) {
168
398
    std::optional<bool> ret = std::nullopt;
169
398
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
170
398
    wolfCrypt_detail::SetGlobalDs(&ds);
171
172
398
    ed25519_key key;
173
398
    bool e25519_key_inited = false;
174
175
398
    WC_CHECK_EQ(wc_ed25519_init(&key), 0);
176
398
    e25519_key_inited = true;
177
178
398
    CF_CHECK_EQ(ed25519LoadPublicKey(key, op.pub.first, ds), true);
179
180
312
    haveAllocFailure = false;
181
312
    ret = wc_ed25519_check_key(&key) == 0;
182
312
    if ( *ret == false && haveAllocFailure == true ) {
183
58
        ret = std::nullopt;
184
58
    }
185
186
398
end:
187
398
    if ( e25519_key_inited == true ) {
188
398
        wc_ed25519_free(&key);
189
398
    }
190
191
398
    wolfCrypt_detail::UnsetGlobalDs();
192
398
    return ret;
193
312
}
194
195
2.37k
std::optional<component::ECDSA_Signature> OpECDSA_Sign_ed25519(operation::ECDSA_Sign& op) {
196
2.37k
    std::optional<component::ECDSA_Signature> ret = std::nullopt;
197
2.37k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
198
2.37k
    wolfCrypt_detail::SetGlobalDs(&ds);
199
200
2.37k
    ed25519_key key;
201
2.37k
    bool e25519_key_inited = false;
202
2.37k
    uint8_t sig[ED25519_SIG_SIZE];
203
2.37k
    word32 sigSz = sizeof(sig);
204
205
2.37k
    WC_CHECK_EQ(wc_ed25519_init(&key), 0);
206
2.37k
    e25519_key_inited = true;
207
208
2.37k
    CF_CHECK_EQ(wolfCrypt_detail::ed25519LoadPrivateKey(key, op.priv, ds), true);
209
2.31k
    CF_CHECK_EQ(wolfCrypt_detail::ed25519DerivePublicKey(key), true);
210
211
    /* Sign message */
212
2.19k
    WC_CHECK_EQ(wc_ed25519_sign_msg(op.cleartext.GetPtr(), op.cleartext.GetSize(), sig, &sigSz, &key), MP_OKAY);
213
1.80k
    CF_CHECK_EQ(sigSz, ED25519_SIG_SIZE);
214
1.80k
    static_assert(ED25519_SIG_SIZE % 2 == 0);
215
216
1.80k
    {
217
1.80k
        std::optional<component::BignumPair> ret_sig;
218
1.80k
        std::optional<component::BignumPair> ret_pub;
219
220
1.80k
        CF_CHECK_NE(ret_sig = wolfCrypt_bignum::Bignum::BinToBignumPair(ds, sig, ED25519_SIG_SIZE), std::nullopt);
221
1.74k
        CF_CHECK_NE(ret_pub = wolfCrypt_detail::ed25519GetPublicKey(key, ds), std::nullopt);
222
223
1.66k
        ret = component::ECDSA_Signature(*ret_sig, *ret_pub);
224
1.66k
    }
225
226
2.37k
end:
227
2.37k
    if ( e25519_key_inited == true ) {
228
2.37k
        wc_ed25519_free(&key);
229
2.37k
    }
230
231
2.37k
    wolfCrypt_detail::UnsetGlobalDs();
232
2.37k
    return ret;
233
1.66k
}
234
235
3.63k
std::optional<bool> OpECDSA_Verify_ed25519(operation::ECDSA_Verify& op) {
236
3.63k
    std::optional<bool> ret = std::nullopt;
237
3.63k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
238
3.63k
    wolfCrypt_detail::SetGlobalDs(&ds);
239
240
3.63k
    ed25519_key key;
241
3.63k
    bool e25519_key_inited = false;
242
3.63k
    uint8_t ed25519sig[ED25519_SIG_SIZE];
243
3.63k
    int verify;
244
3.63k
    bool oneShot = true;
245
246
3.63k
    WC_CHECK_EQ(wc_ed25519_init(&key), 0);
247
3.63k
    e25519_key_inited = true;
248
249
3.63k
    CF_CHECK_EQ(ed25519LoadPublicKey(key, op.signature.pub.first, ds), true);
250
3.55k
    CF_CHECK_EQ(wolfCrypt_bignum::Bignum::ToBin(ds, op.signature.signature, ed25519sig, sizeof(ed25519sig)), true);
251
252
3.46k
#if defined(WOLFSSL_ED25519_STREAMING_VERIFY)
253
3.46k
    try { oneShot = ds.Get<bool>(); } catch ( ... ) { }
254
3.46k
#endif
255
256
3.46k
    if ( oneShot == true ) {
257
2.74k
        WC_CHECK_EQ(wc_ed25519_verify_msg(ed25519sig, sizeof(ed25519sig), op.cleartext.GetPtr(), op.cleartext.GetSize(), &verify, &key), 0);
258
1.54k
    } else {
259
#if !defined(WOLFSSL_ED25519_STREAMING_VERIFY)
260
        CF_UNREACHABLE();
261
#else
262
713
        const auto parts = util::ToParts(ds, op.cleartext);
263
264
713
        WC_CHECK_EQ(wc_ed25519_verify_msg_init(ed25519sig, sizeof(ed25519sig), &key, (byte)Ed25519, nullptr, 0), 0);
265
266
1.86k
        for (const auto& part : parts) {
267
1.86k
            WC_CHECK_EQ(wc_ed25519_verify_msg_update(part.first, part.second, &key), 0);
268
1.61k
        }
269
270
654
        WC_CHECK_EQ(wc_ed25519_verify_msg_final(ed25519sig, sizeof(ed25519sig), &verify, &key), 0);
271
494
#endif
272
494
    }
273
274
1.63k
    ret = verify ? true : false;
275
276
3.63k
end:
277
3.63k
    if ( e25519_key_inited == true ) {
278
3.63k
        wc_ed25519_free(&key);
279
3.63k
    }
280
281
3.63k
    wolfCrypt_detail::UnsetGlobalDs();
282
3.63k
    return ret;
283
1.63k
}
284
285
} /* namespace wolfCrypt_detail */
286
} /* namespace module */
287
} /* namespace cryptofuzz */