/src/cryptofuzz-sp-math-all-8bit/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 */ |