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