/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/module.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "module.h" |
2 | | #include <cryptofuzz/util.h> |
3 | | #include <cryptofuzz/repository.h> |
4 | | #include <fuzzing/datasource/id.hpp> |
5 | | #include "bn_ops.h" |
6 | | extern "C" { |
7 | | #include <wolfssl/openssl/hmac.h> |
8 | | } |
9 | | #if defined(HMAC) |
10 | | #undef HMAC |
11 | | #endif |
12 | | #include "module_internal.h" |
13 | | |
14 | | namespace cryptofuzz { |
15 | | namespace module { |
16 | | |
17 | | wolfCrypt_OpenSSL::wolfCrypt_OpenSSL(void) : |
18 | 2 | Module("wolfCrypt-OpenSSL") { |
19 | 2 | } |
20 | | |
21 | | namespace wolfCrypt_OpenSSL_detail { |
22 | 3.34k | const EVP_MD* toEVPMD(const component::DigestType& digestType) { |
23 | 3.34k | using fuzzing::datasource::ID; |
24 | | |
25 | 3.34k | static const std::map<uint64_t, const EVP_MD*> LUT = { |
26 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
27 | | { CF_DIGEST("SHA1"), EVP_sha1() }, |
28 | | { CF_DIGEST("SHA224"), EVP_sha224() }, |
29 | | { CF_DIGEST("SHA256"), EVP_sha256() }, |
30 | | { CF_DIGEST("SHA384"), EVP_sha384() }, |
31 | | { CF_DIGEST("SHA512"), EVP_sha512() }, |
32 | | { CF_DIGEST("MD4"), EVP_md4() }, |
33 | | { CF_DIGEST("MD5"), EVP_md5() }, |
34 | | { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() }, |
35 | | { CF_DIGEST("SHA512-256"), EVP_sha512_256() }, |
36 | | #elif defined(CRYPTOFUZZ_LIBRESSL) |
37 | | { CF_DIGEST("SHA1"), EVP_sha1() }, |
38 | | { CF_DIGEST("SHA224"), EVP_sha224() }, |
39 | | { CF_DIGEST("SHA256"), EVP_sha256() }, |
40 | | { CF_DIGEST("SHA384"), EVP_sha384() }, |
41 | | { CF_DIGEST("SHA512"), EVP_sha512() }, |
42 | | { CF_DIGEST("MD4"), EVP_md4() }, |
43 | | { CF_DIGEST("MD5"), EVP_md5() }, |
44 | | { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() }, |
45 | | { CF_DIGEST("RIPEMD160"), EVP_ripemd160() }, |
46 | | { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() }, |
47 | | { CF_DIGEST("SM3"), EVP_sm3() }, |
48 | | { CF_DIGEST("GOST-R-34.11-94"), EVP_gostr341194() }, |
49 | | { CF_DIGEST("GOST-28147-89"), EVP_gost2814789imit() }, |
50 | | { CF_DIGEST("STREEBOG-256"), EVP_streebog256() }, |
51 | | { CF_DIGEST("STREEBOG-512"), EVP_streebog512() }, |
52 | | #elif defined(CRYPTOFUZZ_OPENSSL_102) |
53 | | { CF_DIGEST("SHA1"), EVP_sha1() }, |
54 | | { CF_DIGEST("SHA224"), EVP_sha224() }, |
55 | | { CF_DIGEST("SHA256"), EVP_sha256() }, |
56 | | { CF_DIGEST("SHA384"), EVP_sha384() }, |
57 | | { CF_DIGEST("SHA512"), EVP_sha512() }, |
58 | | { CF_DIGEST("MD2"), EVP_md2() }, |
59 | | { CF_DIGEST("MD4"), EVP_md4() }, |
60 | | { CF_DIGEST("MD5"), EVP_md5() }, |
61 | | { CF_DIGEST("MDC2"), EVP_mdc2() }, |
62 | | { CF_DIGEST("RIPEMD160"), EVP_ripemd160() }, |
63 | | { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() }, |
64 | | #elif defined(CRYPTOFUZZ_OPENSSL_110) |
65 | | { CF_DIGEST("SHA1"), EVP_sha1() }, |
66 | | { CF_DIGEST("SHA224"), EVP_sha224() }, |
67 | | { CF_DIGEST("SHA256"), EVP_sha256() }, |
68 | | { CF_DIGEST("SHA384"), EVP_sha384() }, |
69 | | { CF_DIGEST("SHA512"), EVP_sha512() }, |
70 | | { CF_DIGEST("MD2"), EVP_md2() }, |
71 | | { CF_DIGEST("MD4"), EVP_md4() }, |
72 | | { CF_DIGEST("MD5"), EVP_md5() }, |
73 | | { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() }, |
74 | | { CF_DIGEST("MDC2"), EVP_mdc2() }, |
75 | | { CF_DIGEST("RIPEMD160"), EVP_ripemd160() }, |
76 | | { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() }, |
77 | | { CF_DIGEST("BLAKE2B512"), EVP_blake2b512() }, |
78 | | { CF_DIGEST("BLAKE2S256"), EVP_blake2s256() }, |
79 | | #elif defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
80 | 3.34k | { CF_DIGEST("SHA1"), EVP_sha1() }, |
81 | 3.34k | { CF_DIGEST("MDC2"), EVP_mdc2() }, |
82 | 3.34k | { CF_DIGEST("MD4"), EVP_md4() }, |
83 | 3.34k | { CF_DIGEST("MD5"), EVP_md5() }, |
84 | 3.34k | { CF_DIGEST("SHA224"), EVP_sha224() }, |
85 | 3.34k | { CF_DIGEST("SHA256"), EVP_sha256() }, |
86 | 3.34k | { CF_DIGEST("SHA384"), EVP_sha384() }, |
87 | 3.34k | { CF_DIGEST("SHA512"), EVP_sha512() }, |
88 | 3.34k | { CF_DIGEST("RIPEMD160"), EVP_ripemd160() }, |
89 | | #if 0 |
90 | | { CF_DIGEST("MDC2"), EVP_mdc2() }, |
91 | | { CF_DIGEST("MD4"), EVP_md4() }, |
92 | | { CF_DIGEST("MD5"), EVP_md5() }, |
93 | | { CF_DIGEST("SHA1"), EVP_sha1() }, |
94 | | { CF_DIGEST("SHA224"), EVP_sha224() }, |
95 | | { CF_DIGEST("SHA256"), EVP_sha256() }, |
96 | | { CF_DIGEST("SHA384"), EVP_sha384() }, |
97 | | { CF_DIGEST("SHA512"), EVP_sha512() }, |
98 | | { CF_DIGEST("RIPEMD160"), EVP_ripemd160() }, |
99 | | { CF_DIGEST("SHA3-224"), EVP_sha3_224() }, |
100 | | { CF_DIGEST("SHA3-256"), EVP_sha3_256() }, |
101 | | { CF_DIGEST("SHA3-384"), EVP_sha3_384() }, |
102 | | { CF_DIGEST("SHA3-512"), EVP_sha3_512() }, |
103 | | #endif |
104 | | #else |
105 | | { CF_DIGEST("SHA1"), EVP_sha1() }, |
106 | | { CF_DIGEST("SHA224"), EVP_sha224() }, |
107 | | { CF_DIGEST("SHA256"), EVP_sha256() }, |
108 | | { CF_DIGEST("SHA384"), EVP_sha384() }, |
109 | | { CF_DIGEST("SHA512"), EVP_sha512() }, |
110 | | { CF_DIGEST("MD2"), EVP_md2() }, |
111 | | { CF_DIGEST("MD4"), EVP_md4() }, |
112 | | { CF_DIGEST("MD5"), EVP_md5() }, |
113 | | { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() }, |
114 | | { CF_DIGEST("MDC2"), EVP_mdc2() }, |
115 | | { CF_DIGEST("RIPEMD160"), EVP_ripemd160() }, |
116 | | { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() }, |
117 | | { CF_DIGEST("SM3"), EVP_sm3() }, |
118 | | { CF_DIGEST("BLAKE2B512"), EVP_blake2b512() }, |
119 | | { CF_DIGEST("BLAKE2S256"), EVP_blake2s256() }, |
120 | | { CF_DIGEST("SHAKE128"), EVP_shake128() }, |
121 | | { CF_DIGEST("SHAKE256"), EVP_shake256() }, |
122 | | { CF_DIGEST("SHA3-224"), EVP_sha3_224() }, |
123 | | { CF_DIGEST("SHA3-256"), EVP_sha3_256() }, |
124 | | { CF_DIGEST("SHA3-384"), EVP_sha3_384() }, |
125 | | { CF_DIGEST("SHA3-512"), EVP_sha3_512() }, |
126 | | { CF_DIGEST("SHA512-224"), EVP_sha512_224() }, |
127 | | { CF_DIGEST("SHA512-256"), EVP_sha512_256() }, |
128 | | #endif |
129 | 3.34k | }; |
130 | | |
131 | 3.34k | if ( LUT.find(digestType.Get()) == LUT.end() ) { |
132 | 869 | return nullptr; |
133 | 869 | } |
134 | | |
135 | 2.47k | return LUT.at(digestType.Get()); |
136 | 3.34k | } |
137 | | } |
138 | | |
139 | 897 | std::optional<component::Digest> wolfCrypt_OpenSSL::OpDigest(operation::Digest& op) { |
140 | 897 | std::optional<component::Digest> ret = std::nullopt; |
141 | 897 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
142 | | |
143 | 897 | util::Multipart parts; |
144 | | |
145 | 897 | CF_EVP_MD_CTX ctx(ds); |
146 | 897 | const EVP_MD* md = nullptr; |
147 | | |
148 | | /* Initialize */ |
149 | 897 | { |
150 | 897 | parts = util::ToParts(ds, op.cleartext); |
151 | 897 | CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr); |
152 | 563 | CF_CHECK_EQ(EVP_DigestInit_ex(ctx.GetPtr(), md, nullptr), 1); |
153 | 563 | } |
154 | | |
155 | | /* Process */ |
156 | 23.1k | for (const auto& part : parts) { |
157 | 23.1k | CF_CHECK_EQ(EVP_DigestUpdate(ctx.GetPtr(), part.first, part.second), 1); |
158 | 23.1k | } |
159 | | |
160 | | /* Finalize */ |
161 | 563 | { |
162 | 563 | unsigned int len = -1; |
163 | 563 | unsigned char md[EVP_MAX_MD_SIZE]; |
164 | 563 | CF_CHECK_EQ(EVP_DigestFinal_ex(ctx.GetPtr(), md, &len), 1); |
165 | | |
166 | 563 | ret = component::Digest(md, len); |
167 | 563 | } |
168 | | |
169 | 897 | end: |
170 | 897 | return ret; |
171 | 563 | } |
172 | | |
173 | | namespace wolfCrypt_OpenSSL_detail { |
174 | 736 | std::optional<component::MAC> OpHMAC_EVP(operation::HMAC& op, Datasource& ds) { |
175 | 736 | std::optional<component::MAC> ret = std::nullopt; |
176 | | |
177 | 736 | util::Multipart parts; |
178 | | |
179 | 736 | CF_EVP_MD_CTX ctx(ds); |
180 | 736 | const EVP_MD* md = nullptr; |
181 | 736 | EVP_PKEY *pkey = nullptr; |
182 | | |
183 | | /* Initialize */ |
184 | 736 | { |
185 | 736 | parts = util::ToParts(ds, op.cleartext); |
186 | | |
187 | 736 | CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr); |
188 | 531 | CF_CHECK_NE(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, op.cipher.key.GetPtr(), op.cipher.key.GetSize()), nullptr); |
189 | 531 | CF_CHECK_EQ(EVP_DigestSignInit(ctx.GetPtr(), nullptr, md, nullptr, pkey), 1); |
190 | 468 | } |
191 | | |
192 | | /* Process */ |
193 | 8.76k | for (const auto& part : parts) { |
194 | 8.76k | CF_CHECK_EQ(EVP_DigestSignUpdate(ctx.GetPtr(), part.first, part.second), 1); |
195 | 8.60k | } |
196 | | |
197 | | /* Finalize */ |
198 | 305 | { |
199 | 305 | size_t len = -1; |
200 | 305 | uint8_t out[EVP_MAX_MD_SIZE]; |
201 | 305 | CF_CHECK_EQ(EVP_DigestSignFinal(ctx.GetPtr(), out, &len), 1); |
202 | | |
203 | 305 | ret = component::MAC(out, len); |
204 | 305 | } |
205 | | |
206 | 736 | end: |
207 | 736 | EVP_PKEY_free(pkey); |
208 | | |
209 | 736 | return ret; |
210 | 305 | } |
211 | | |
212 | 136 | std::optional<component::MAC> OpHMAC_HMAC(operation::HMAC& op, Datasource& ds) { |
213 | 136 | std::optional<component::MAC> ret = std::nullopt; |
214 | | |
215 | 136 | util::Multipart parts; |
216 | | |
217 | 136 | CF_HMAC_CTX ctx(ds); |
218 | 136 | const EVP_MD* md = nullptr; |
219 | | |
220 | | /* Initialize */ |
221 | 136 | { |
222 | 136 | parts = util::ToParts(ds, op.cleartext); |
223 | | /* TODO remove ? */ |
224 | 136 | HMAC_CTX_reset(ctx.GetPtr()); |
225 | 136 | CF_CHECK_NE(md = toEVPMD(op.digestType), nullptr); |
226 | 120 | CF_CHECK_EQ(HMAC_Init_ex(ctx.GetPtr(), op.cipher.key.GetPtr(), op.cipher.key.GetSize(), md, nullptr), 1); |
227 | 91 | } |
228 | | |
229 | | /* Process */ |
230 | 3.81k | for (const auto& part : parts) { |
231 | 3.81k | CF_CHECK_EQ(HMAC_Update(ctx.GetPtr(), part.first, part.second), 1); |
232 | 3.81k | } |
233 | | |
234 | | /* Finalize */ |
235 | 91 | { |
236 | 91 | unsigned int len = -1; |
237 | 91 | uint8_t out[EVP_MAX_MD_SIZE]; |
238 | 91 | CF_CHECK_EQ(HMAC_Final(ctx.GetPtr(), out, &len), 1); |
239 | | |
240 | 91 | ret = component::MAC(out, len); |
241 | 91 | } |
242 | | |
243 | 136 | end: |
244 | 136 | return ret; |
245 | 91 | } |
246 | | } |
247 | | |
248 | 872 | std::optional<component::MAC> wolfCrypt_OpenSSL::OpHMAC(operation::HMAC& op) { |
249 | 872 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
250 | | |
251 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
252 | | if ( op.digestType.Get() == CF_DIGEST("SIPHASH64") || |
253 | | op.digestType.Get() == CF_DIGEST("SIPHASH128") ) { |
254 | | /* Not HMAC but invoking SipHash here anyway due to convenience. */ |
255 | | return OpenSSL_detail::SipHash(op); |
256 | | } |
257 | | #endif |
258 | | |
259 | 872 | bool useEVP = true; |
260 | 872 | try { |
261 | 872 | useEVP = ds.Get<bool>(); |
262 | 872 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
263 | 187 | } |
264 | | |
265 | 872 | if ( useEVP == true ) { |
266 | 736 | #if !defined(CRYPTOFUZZ_BORINGSSL) |
267 | 736 | return wolfCrypt_OpenSSL_detail::OpHMAC_EVP(op, ds); |
268 | | #else |
269 | | return wolfCrypt_OpenSSL_detail::OpHMAC_HMAC(op, ds); |
270 | | #endif |
271 | 736 | } else { |
272 | 136 | #if !defined(CRYPTOFUZZ_OPENSSL_102) |
273 | 136 | return wolfCrypt_OpenSSL_detail::OpHMAC_HMAC(op, ds); |
274 | | #else |
275 | | return wolfCrypt_OpenSSL_detail::OpHMAC_EVP(op, ds); |
276 | | #endif |
277 | 136 | } |
278 | | |
279 | 0 | return {}; |
280 | 872 | } |
281 | | |
282 | | namespace wolfCrypt_OpenSSL_detail { |
283 | | |
284 | 5.83k | const EVP_CIPHER* toEVPCIPHER(const component::SymmetricCipherType cipherType) { |
285 | 5.83k | using fuzzing::datasource::ID; |
286 | | |
287 | 5.83k | switch ( cipherType.Get() ) { |
288 | 434 | case CF_CIPHER("AES_128_CBC"): |
289 | 434 | return EVP_aes_128_cbc(); |
290 | 270 | case CF_CIPHER("AES_128_CFB1"): |
291 | 270 | return EVP_aes_128_cfb1(); |
292 | 98 | case CF_CIPHER("AES_128_CFB8"): |
293 | 98 | return EVP_aes_128_cfb8(); |
294 | 176 | case CF_CIPHER("AES_128_CTR"): |
295 | 176 | return EVP_aes_128_ctr(); |
296 | 89 | case CF_CIPHER("AES_128_ECB"): |
297 | 89 | return EVP_aes_128_ecb(); |
298 | 398 | case CF_CIPHER("AES_128_GCM"): |
299 | 398 | return EVP_aes_128_gcm(); |
300 | 245 | case CF_CIPHER("AES_128_OFB"): |
301 | 245 | return EVP_aes_128_ofb(); |
302 | 169 | case CF_CIPHER("AES_128_XTS"): |
303 | 169 | return EVP_aes_128_xts(); |
304 | 108 | case CF_CIPHER("AES_192_CBC"): |
305 | 108 | return EVP_aes_192_cbc(); |
306 | 50 | case CF_CIPHER("AES_192_CFB1"): |
307 | 50 | return EVP_aes_192_cfb1(); |
308 | 152 | case CF_CIPHER("AES_192_CFB8"): |
309 | 152 | return EVP_aes_192_cfb8(); |
310 | 161 | case CF_CIPHER("AES_192_CTR"): |
311 | 161 | return EVP_aes_192_ctr(); |
312 | 90 | case CF_CIPHER("AES_192_ECB"): |
313 | 90 | return EVP_aes_192_ecb(); |
314 | 288 | case CF_CIPHER("AES_192_GCM"): |
315 | 288 | return EVP_aes_192_gcm(); |
316 | 140 | case CF_CIPHER("AES_192_OFB"): |
317 | 140 | return EVP_aes_192_ofb(); |
318 | 114 | case CF_CIPHER("AES_256_CBC"): |
319 | 114 | return EVP_aes_256_cbc(); |
320 | 183 | case CF_CIPHER("AES_256_CFB1"): |
321 | 183 | return EVP_aes_256_cfb1(); |
322 | 118 | case CF_CIPHER("AES_256_CFB8"): |
323 | 118 | return EVP_aes_256_cfb8(); |
324 | 118 | case CF_CIPHER("AES_256_CTR"): |
325 | 118 | return EVP_aes_256_ctr(); |
326 | 46 | case CF_CIPHER("AES_256_ECB"): |
327 | 46 | return EVP_aes_256_ecb(); |
328 | 532 | case CF_CIPHER("AES_256_GCM"): |
329 | 532 | return EVP_aes_256_gcm(); |
330 | 195 | case CF_CIPHER("AES_256_OFB"): |
331 | 195 | return EVP_aes_256_ofb(); |
332 | 78 | case CF_CIPHER("AES_256_XTS"): |
333 | 78 | return EVP_aes_256_xts(); |
334 | 251 | case CF_CIPHER("DES_CBC"): |
335 | 251 | return EVP_des_cbc(); |
336 | 361 | case CF_CIPHER("DES_ECB"): |
337 | 361 | return EVP_des_ecb(); |
338 | 114 | case CF_CIPHER("DES_EDE3_CBC"): |
339 | 114 | return EVP_des_ede3_cbc(); |
340 | 43 | case CF_CIPHER("RC4"): |
341 | 43 | return EVP_rc4(); |
342 | 814 | default: |
343 | 814 | return nullptr; |
344 | 5.83k | } |
345 | 5.83k | } |
346 | | |
347 | 1.24k | inline bool isAEAD(const EVP_CIPHER* ctx) { |
348 | 1.24k | return (EVP_CIPHER_flags(ctx) & EVP_CIPH_GCM_MODE) == EVP_CIPH_GCM_MODE; |
349 | 1.24k | } |
350 | | |
351 | 4.42k | bool checkSetIVLength(const uint64_t cipherType, const EVP_CIPHER* cipher, EVP_CIPHER_CTX* ctx, const size_t inputIvLength) { |
352 | 4.42k | bool ret = false; |
353 | | |
354 | 4.42k | const size_t ivLength = EVP_CIPHER_iv_length(cipher); |
355 | 4.42k | const bool ivLengthMismatch = ivLength != inputIvLength; |
356 | | |
357 | 4.42k | return !ivLengthMismatch; |
358 | 0 | if ( isAEAD(cipher) == false ) { |
359 | | /* Return true (success) if input IV length is expected IV length */ |
360 | 0 | return !ivLengthMismatch; |
361 | 0 | } |
362 | | |
363 | 0 | const bool isCCM = repository::IsCCM( cipherType ); |
364 | | |
365 | | /* Only AEAD ciphers past this point */ |
366 | | |
367 | | /* EVP_CIPHER_iv_length may return the wrong default IV length for CCM ciphers. |
368 | | * Eg. EVP_CIPHER_iv_length returns 12 for EVP_aes_128_ccm() even though the |
369 | | * IV length is actually. |
370 | | * |
371 | | * Hence, with CCM ciphers set the desired IV length always. |
372 | | */ |
373 | |
|
374 | 0 | if ( isCCM || ivLengthMismatch ) { |
375 | 0 | CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, inputIvLength, nullptr), 1); |
376 | 0 | } |
377 | | |
378 | 0 | ret = true; |
379 | 0 | end: |
380 | |
|
381 | 0 | return ret; |
382 | 0 | } |
383 | | |
384 | 3.89k | bool checkSetKeyLength(const EVP_CIPHER* cipher, EVP_CIPHER_CTX* ctx, const size_t inputKeyLength) { |
385 | 3.89k | (void)ctx; |
386 | | |
387 | 3.89k | bool ret = false; |
388 | | |
389 | 3.89k | const size_t keyLength = EVP_CIPHER_key_length(cipher); |
390 | 3.89k | if ( keyLength != inputKeyLength ) { |
391 | 209 | return false; |
392 | 0 | CF_CHECK_EQ(EVP_CIPHER_CTX_set_key_length(ctx, inputKeyLength), 1); |
393 | 0 | } |
394 | | |
395 | 3.68k | ret = true; |
396 | | |
397 | 3.68k | end: |
398 | 3.68k | return ret; |
399 | 3.68k | } |
400 | | |
401 | 2.56k | std::optional<component::Ciphertext> OpSymmetricEncrypt_EVP(operation::SymmetricEncrypt& op, Datasource& ds) { |
402 | 2.56k | std::optional<component::Ciphertext> ret = std::nullopt; |
403 | | |
404 | 2.56k | util::Multipart partsCleartext, partsAAD; |
405 | | |
406 | 2.56k | const EVP_CIPHER* cipher = nullptr; |
407 | 2.56k | CF_EVP_CIPHER_CTX ctx(ds); |
408 | | |
409 | 2.56k | size_t out_size = op.ciphertextSize; |
410 | 2.56k | size_t outIdx = 0; |
411 | 2.56k | uint8_t* out = util::malloc(out_size); |
412 | 2.56k | uint8_t* outTag = op.tagSize != std::nullopt ? util::malloc(*op.tagSize) : nullptr; |
413 | | |
414 | | /* Initialize */ |
415 | 2.56k | { |
416 | 2.56k | CF_CHECK_NE(cipher = wolfCrypt_OpenSSL_detail::toEVPCIPHER(op.cipher.cipherType), nullptr); |
417 | 2.21k | if ( op.tagSize != std::nullopt || op.aad != std::nullopt ) { |
418 | | /* Trying to treat non-AEAD with AEAD-specific features (tag, aad) |
419 | | * leads to all kinds of gnarly memory bugs in OpenSSL. |
420 | | * It is quite arguably misuse of the OpenSSL API, so don't do this. |
421 | | */ |
422 | 655 | CF_CHECK_EQ(isAEAD(cipher), true); |
423 | 549 | } |
424 | | |
425 | 2.11k | CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), cipher, nullptr, nullptr, nullptr), 1); |
426 | | |
427 | | /* Must be a multiple of the block size of this cipher */ |
428 | | //CF_CHECK_EQ(op.cleartext.GetSize() % EVP_CIPHER_block_size(cipher), 0); |
429 | | |
430 | | /* Convert cleartext to parts */ |
431 | 2.11k | partsCleartext = util::CipherInputTransform(ds, op.cipher.cipherType, out, out_size, op.cleartext.GetPtr(), op.cleartext.GetSize()); |
432 | | |
433 | 2.11k | if ( op.aad != std::nullopt ) { |
434 | 233 | if ( repository::IsCCM( op.cipher.cipherType.Get() ) ) { |
435 | | /* CCM does not support chunked AAD updating. |
436 | | * See: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_CCM_mode |
437 | | */ |
438 | 0 | partsAAD = { {op.aad->GetPtr(), op.aad->GetSize()} }; |
439 | 233 | } else { |
440 | 233 | partsAAD = util::ToParts(ds, *(op.aad)); |
441 | 233 | } |
442 | 233 | } |
443 | | |
444 | 2.11k | if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) { |
445 | 2.11k | CF_CHECK_EQ(checkSetIVLength(op.cipher.cipherType.Get(), cipher, ctx.GetPtr(), op.cipher.iv.GetSize()), true); |
446 | 1.88k | } else { |
447 | 0 | CF_CHECK_EQ(op.cipher.iv.GetSize(), 12); |
448 | 0 | } |
449 | 1.88k | CF_CHECK_EQ(checkSetKeyLength(cipher, ctx.GetPtr(), op.cipher.key.GetSize()), true); |
450 | | |
451 | 1.77k | if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) { |
452 | 1.77k | CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), op.cipher.iv.GetPtr()), 1); |
453 | 1.77k | } else { |
454 | | /* Prepend the 32 bit counter (which is 0) to the iv */ |
455 | 0 | uint8_t cc20IV[16]; |
456 | 0 | memset(cc20IV, 0, 4); |
457 | 0 | memcpy(cc20IV + 4, op.cipher.iv.GetPtr(), op.cipher.iv.GetSize()); |
458 | 0 | CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), cc20IV), 1); |
459 | 0 | } |
460 | | |
461 | | /* Disable ECB padding for consistency with mbed TLS */ |
462 | 1.77k | if ( repository::IsECB(op.cipher.cipherType.Get()) ) { |
463 | 246 | CF_CHECK_EQ(EVP_CIPHER_CTX_set_padding(ctx.GetPtr(), 0), 1); |
464 | 246 | } |
465 | 1.77k | } |
466 | | |
467 | | /* Process */ |
468 | 1.77k | { |
469 | | /* If the cipher is CCM, the total cleartext size needs to be indicated explicitly |
470 | | * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption |
471 | | */ |
472 | 1.77k | if ( repository::IsCCM(op.cipher.cipherType.Get()) == true ) { |
473 | 0 | int len; |
474 | 0 | CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), nullptr, &len, nullptr, op.cleartext.GetSize()), 1); |
475 | 0 | } |
476 | | |
477 | | /* Set AAD */ |
478 | 1.77k | if ( op.aad != std::nullopt ) { |
479 | 148 | for (const auto& part : partsAAD) { |
480 | 148 | int len; |
481 | 148 | CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), nullptr, &len, part.first, part.second), 1); |
482 | 148 | } |
483 | 148 | } |
484 | | |
485 | 34.4k | for (const auto& part : partsCleartext) { |
486 | | /* "the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1)" */ |
487 | 34.4k | CF_CHECK_GTE(out_size, part.second + EVP_CIPHER_block_size(cipher) - 1); |
488 | | |
489 | 34.2k | int len = -1; |
490 | 34.2k | CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), out + outIdx, &len, part.first, part.second), 1); |
491 | 34.2k | outIdx += len; |
492 | 34.2k | out_size -= len; |
493 | 34.2k | } |
494 | 1.77k | } |
495 | | |
496 | | /* Finalize */ |
497 | 1.58k | { |
498 | 1.58k | CF_CHECK_GTE(out_size, static_cast<size_t>(EVP_CIPHER_block_size(cipher))); |
499 | | |
500 | 1.56k | int len = -1; |
501 | 1.56k | CF_CHECK_EQ(EVP_EncryptFinal_ex(ctx.GetPtr(), out + outIdx, &len), 1); |
502 | 1.51k | outIdx += len; |
503 | | |
504 | 1.51k | if ( op.tagSize != std::nullopt ) { |
505 | | /* Get tag. |
506 | | * |
507 | | * See comments around EVP_CTRL_AEAD_SET_TAG in OpSymmetricDecrypt_EVP for reasons |
508 | | * as to why this is disabled for LibreSSL. |
509 | | */ |
510 | 449 | CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx.GetPtr(), EVP_CTRL_AEAD_GET_TAG, *op.tagSize, outTag), 1); |
511 | 192 | ret = component::Ciphertext(Buffer(out, outIdx), Buffer(outTag, *op.tagSize)); |
512 | 1.06k | } else { |
513 | 1.06k | ret = component::Ciphertext(Buffer(out, outIdx)); |
514 | 1.06k | } |
515 | 1.51k | } |
516 | | |
517 | 2.56k | end: |
518 | | |
519 | 2.56k | util::free(out); |
520 | 2.56k | util::free(outTag); |
521 | | |
522 | 2.56k | return ret; |
523 | 1.51k | } |
524 | | |
525 | | } |
526 | | |
527 | 2.56k | std::optional<component::Ciphertext> wolfCrypt_OpenSSL::OpSymmetricEncrypt(operation::SymmetricEncrypt& op) { |
528 | 2.56k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
529 | 2.56k | return wolfCrypt_OpenSSL_detail::OpSymmetricEncrypt_EVP(op, ds); |
530 | 2.56k | } |
531 | | |
532 | | namespace wolfCrypt_OpenSSL_detail { |
533 | | |
534 | 2.56k | std::optional<component::Cleartext> OpSymmetricDecrypt_EVP(operation::SymmetricDecrypt& op, Datasource& ds) { |
535 | 2.56k | std::optional<component::Cleartext> ret = std::nullopt; |
536 | | |
537 | 2.56k | util::Multipart partsCiphertext, partsAAD; |
538 | | |
539 | 2.56k | const EVP_CIPHER* cipher = nullptr; |
540 | 2.56k | CF_EVP_CIPHER_CTX ctx(ds); |
541 | | |
542 | 2.56k | size_t out_size = op.cleartextSize; |
543 | 2.56k | size_t outIdx = 0; |
544 | 2.56k | uint8_t* out = util::malloc(out_size); |
545 | | |
546 | | /* Initialize */ |
547 | 2.56k | { |
548 | 2.56k | CF_CHECK_NE(cipher = toEVPCIPHER(op.cipher.cipherType), nullptr); |
549 | 2.35k | if ( op.tag != std::nullopt || op.aad != std::nullopt ) { |
550 | | /* Trying to treat non-AEAD with AEAD-specific features (tag, aad) |
551 | | * leads to all kinds of gnarly memory bugs in OpenSSL. |
552 | | * It is quite arguably misuse of the OpenSSL API, so don't do this. |
553 | | */ |
554 | 585 | CF_CHECK_EQ(isAEAD(cipher), true); |
555 | 538 | } |
556 | 2.31k | CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), cipher, nullptr, nullptr, nullptr), 1); |
557 | | |
558 | | /* Must be a multiple of the block size of this cipher */ |
559 | | //CF_CHECK_EQ(op.ciphertext.GetSize() % EVP_CIPHER_block_size(cipher), 0); |
560 | | |
561 | | /* Convert ciphertext to parts */ |
562 | | //partsCiphertext = util::CipherInputTransform(ds, op.cipher.cipherType, out, out_size, op.ciphertext.GetPtr(), op.ciphertext.GetSize()); |
563 | 2.31k | partsCiphertext = { {op.ciphertext.GetPtr(), op.ciphertext.GetSize()} }; |
564 | | |
565 | 2.31k | if ( op.aad != std::nullopt ) { |
566 | 320 | if ( repository::IsCCM( op.cipher.cipherType.Get() ) ) { |
567 | | /* CCM does not support chunked AAD updating. |
568 | | * See: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_CCM_mode |
569 | | */ |
570 | 0 | partsAAD = { {op.aad->GetPtr(), op.aad->GetSize()} }; |
571 | 320 | } else { |
572 | 320 | partsAAD = util::ToParts(ds, *(op.aad)); |
573 | 320 | } |
574 | 320 | } |
575 | | |
576 | 2.31k | if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) { |
577 | 2.31k | CF_CHECK_EQ(checkSetIVLength(op.cipher.cipherType.Get(), cipher, ctx.GetPtr(), op.cipher.iv.GetSize()), true); |
578 | 2.00k | } else { |
579 | 0 | CF_CHECK_EQ(op.cipher.iv.GetSize(), 12); |
580 | 0 | } |
581 | 2.00k | CF_CHECK_EQ(checkSetKeyLength(cipher, ctx.GetPtr(), op.cipher.key.GetSize()), true); |
582 | | |
583 | 1.91k | if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) { |
584 | 1.91k | CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), op.cipher.iv.GetPtr()), 1); |
585 | 1.91k | } else { |
586 | | /* Prepend the 32 bit counter (which is 0) to the iv */ |
587 | 0 | uint8_t cc20IV[16]; |
588 | 0 | memset(cc20IV, 0, 4); |
589 | 0 | memcpy(cc20IV + 4, op.cipher.iv.GetPtr(), op.cipher.iv.GetSize()); |
590 | 0 | CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), cc20IV), 1); |
591 | 0 | } |
592 | | |
593 | | /* Disable ECB padding for consistency with mbed TLS */ |
594 | 1.91k | if ( repository::IsECB(op.cipher.cipherType.Get()) ) { |
595 | 196 | CF_CHECK_EQ(EVP_CIPHER_CTX_set_padding(ctx.GetPtr(), 0), 1); |
596 | 196 | } |
597 | 1.91k | } |
598 | | |
599 | | /* Process */ |
600 | 1.91k | { |
601 | | /* If the cipher is CCM, the total cleartext size needs to be indicated explicitly |
602 | | * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption |
603 | | */ |
604 | 1.91k | if ( repository::IsCCM(op.cipher.cipherType.Get()) == true ) { |
605 | 0 | int len; |
606 | 0 | CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), nullptr, &len, nullptr, op.ciphertext.GetSize()), 1); |
607 | 0 | } |
608 | | |
609 | | /* Set AAD */ |
610 | 1.91k | if ( op.aad != std::nullopt ) { |
611 | 3.51k | for (const auto& part : partsAAD) { |
612 | 3.51k | int len; |
613 | 3.51k | CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), nullptr, &len, part.first, part.second), 1); |
614 | 3.51k | } |
615 | 180 | } |
616 | | |
617 | | /* Set ciphertext */ |
618 | 1.91k | for (const auto& part : partsCiphertext) { |
619 | 1.91k | CF_CHECK_GTE(out_size, part.second + EVP_CIPHER_block_size(cipher)); |
620 | | |
621 | 1.84k | int len = -1; |
622 | 1.84k | CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), out + outIdx, &len, part.first, part.second), 1); |
623 | | |
624 | 1.83k | outIdx += len; |
625 | 1.83k | out_size -= len; |
626 | 1.83k | } |
627 | | |
628 | 1.83k | if ( op.tag != std::nullopt ) { |
629 | 263 | CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx.GetPtr(), EVP_CTRL_AEAD_SET_TAG, op.tag->GetSize(), (void*)op.tag->GetPtr()), 1); |
630 | 231 | } |
631 | 1.83k | } |
632 | | |
633 | | /* Finalize */ |
634 | 1.80k | { |
635 | 1.80k | CF_CHECK_GTE(out_size, static_cast<size_t>(EVP_CIPHER_block_size(cipher))); |
636 | | |
637 | 1.80k | int len = -1; |
638 | 1.80k | CF_CHECK_EQ(EVP_DecryptFinal_ex(ctx.GetPtr(), out + outIdx, &len), 1); |
639 | 1.43k | outIdx += len; |
640 | | |
641 | 1.43k | ret = component::Cleartext(out, outIdx); |
642 | 1.43k | } |
643 | | |
644 | 2.56k | end: |
645 | | |
646 | 2.56k | util::free(out); |
647 | | |
648 | 2.56k | return ret; |
649 | 1.43k | } |
650 | | |
651 | | } |
652 | | |
653 | 2.56k | std::optional<component::Cleartext> wolfCrypt_OpenSSL::OpSymmetricDecrypt(operation::SymmetricDecrypt& op) { |
654 | 2.56k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
655 | 2.56k | return wolfCrypt_OpenSSL_detail::OpSymmetricDecrypt_EVP(op, ds); |
656 | 2.56k | } |
657 | | |
658 | 702 | std::optional<component::MAC> wolfCrypt_OpenSSL::OpCMAC(operation::CMAC& op) { |
659 | 702 | std::optional<component::MAC> ret = std::nullopt; |
660 | 702 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
661 | | |
662 | 702 | util::Multipart parts; |
663 | | |
664 | 702 | CF_CMAC_CTX ctx(ds); |
665 | 702 | const EVP_CIPHER* cipher = nullptr; |
666 | | |
667 | | /* Initialize */ |
668 | 702 | { |
669 | 702 | parts = util::ToParts(ds, op.cleartext); |
670 | | |
671 | 702 | CF_CHECK_NE(cipher = wolfCrypt_OpenSSL_detail::toEVPCIPHER(op.cipher.cipherType), nullptr); |
672 | 445 | CF_CHECK_EQ(CMAC_Init(ctx.GetPtr(), op.cipher.key.GetPtr(), op.cipher.key.GetSize(), cipher, nullptr), 1); |
673 | 233 | } |
674 | | |
675 | | /* Process */ |
676 | 1.38k | for (const auto& part : parts) { |
677 | 1.38k | CF_CHECK_EQ(CMAC_Update(ctx.GetPtr(), part.first, part.second), 1); |
678 | 1.38k | } |
679 | | |
680 | | /* Finalize */ |
681 | 233 | { |
682 | 233 | size_t len = 0; |
683 | 233 | uint8_t out[EVP_MAX_MD_SIZE]; |
684 | 233 | CF_CHECK_EQ(CMAC_Final(ctx.GetPtr(), out, &len), 1); |
685 | 233 | ret = component::MAC(out, len); |
686 | 233 | } |
687 | | |
688 | 702 | end: |
689 | 702 | return ret; |
690 | 233 | } |
691 | | |
692 | 904 | std::optional<component::Key> wolfCrypt_OpenSSL::OpKDF_HKDF(operation::KDF_HKDF& op) { |
693 | 904 | std::optional<component::Key> ret = std::nullopt; |
694 | 904 | EVP_PKEY_CTX* pctx = nullptr; |
695 | 904 | const EVP_MD* md = nullptr; |
696 | | |
697 | 904 | size_t out_size = op.keySize; |
698 | 904 | uint8_t* out = util::malloc(out_size); |
699 | | |
700 | | /* Initialize */ |
701 | 904 | { |
702 | 904 | CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr); |
703 | 745 | CF_CHECK_NE(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr), nullptr); |
704 | 745 | CF_CHECK_EQ(EVP_PKEY_derive_init(pctx), 1); |
705 | 745 | CF_CHECK_EQ(EVP_PKEY_CTX_set_hkdf_md(pctx, md), 1); |
706 | 745 | CF_CHECK_EQ(EVP_PKEY_CTX_set1_hkdf_key(pctx, op.password.GetPtr(), op.password.GetSize()), 1); |
707 | 611 | CF_CHECK_EQ(EVP_PKEY_CTX_set1_hkdf_salt(pctx, op.salt.GetPtr(), op.salt.GetSize()), 1); |
708 | 611 | CF_CHECK_EQ(EVP_PKEY_CTX_add1_hkdf_info(pctx, op.info.GetPtr(), op.info.GetSize()), 1); |
709 | 611 | } |
710 | | |
711 | | /* Process/finalize */ |
712 | 0 | { |
713 | 611 | CF_CHECK_EQ(EVP_PKEY_derive(pctx, out, &out_size) , 1); |
714 | | |
715 | 411 | CF_CHECK_NE(out, nullptr); |
716 | | |
717 | 411 | ret = component::Key(out, out_size); |
718 | 411 | } |
719 | | |
720 | 904 | end: |
721 | 904 | EVP_PKEY_CTX_free(pctx); |
722 | | |
723 | 904 | util::free(out); |
724 | | |
725 | 904 | return ret; |
726 | 411 | } |
727 | | |
728 | 674 | std::optional<component::Key> wolfCrypt_OpenSSL::OpKDF_PBKDF2(operation::KDF_PBKDF2& op) { |
729 | 674 | std::optional<component::Key> ret = std::nullopt; |
730 | 674 | const EVP_MD* md = nullptr; |
731 | | |
732 | 674 | const size_t outSize = op.keySize; |
733 | 674 | uint8_t* out = util::malloc(outSize); |
734 | | |
735 | 674 | CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr); |
736 | 482 | CF_CHECK_EQ(PKCS5_PBKDF2_HMAC( |
737 | 482 | (const char*)(op.password.GetPtr()), |
738 | 482 | op.password.GetSize(), |
739 | 482 | op.salt.GetPtr(), |
740 | 482 | op.salt.GetSize(), |
741 | 482 | op.iterations, |
742 | 482 | md, |
743 | 482 | outSize, |
744 | 482 | out), 1); |
745 | | |
746 | 427 | ret = component::Key(out, outSize); |
747 | 674 | end: |
748 | 674 | util::free(out); |
749 | | |
750 | 674 | return ret; |
751 | 427 | } |
752 | | |
753 | 4.01k | static std::optional<int> toCurveNID(const component::CurveType& curveType) { |
754 | 4.01k | static const std::map<uint64_t, int> LUT = { |
755 | 4.01k | { CF_ECC_CURVE("secp192r1"), NID_X9_62_prime192v1 }, |
756 | 4.01k | { CF_ECC_CURVE("x962_p192v2"), NID_X9_62_prime192v2 }, |
757 | 4.01k | { CF_ECC_CURVE("x962_p192v3"), NID_X9_62_prime192v3 }, |
758 | 4.01k | { CF_ECC_CURVE("x962_p239v1"), NID_X9_62_prime239v1 }, |
759 | 4.01k | { CF_ECC_CURVE("x962_p239v2"), NID_X9_62_prime239v2 }, |
760 | 4.01k | { CF_ECC_CURVE("x962_p239v3"), NID_X9_62_prime239v3 }, |
761 | 4.01k | { CF_ECC_CURVE("secp256r1"), NID_X9_62_prime256v1 }, |
762 | 4.01k | { CF_ECC_CURVE("brainpool160r1"), NID_brainpoolP160r1 }, |
763 | 4.01k | { CF_ECC_CURVE("brainpool192r1"), NID_brainpoolP192r1 }, |
764 | 4.01k | { CF_ECC_CURVE("brainpool224r1"), NID_brainpoolP224r1 }, |
765 | 4.01k | { CF_ECC_CURVE("brainpool256r1"), NID_brainpoolP256r1 }, |
766 | 4.01k | { CF_ECC_CURVE("brainpool320r1"), NID_brainpoolP320r1 }, |
767 | 4.01k | { CF_ECC_CURVE("brainpool384r1"), NID_brainpoolP384r1 }, |
768 | 4.01k | { CF_ECC_CURVE("brainpool512r1"), NID_brainpoolP512r1 }, |
769 | 4.01k | { CF_ECC_CURVE("secp112r1"), NID_secp112r1 }, |
770 | 4.01k | { CF_ECC_CURVE("secp112r2"), NID_secp112r2 }, |
771 | 4.01k | { CF_ECC_CURVE("secp128r1"), NID_secp128r1 }, |
772 | 4.01k | { CF_ECC_CURVE("secp128r2"), NID_secp128r2 }, |
773 | 4.01k | { CF_ECC_CURVE("secp160k1"), NID_secp160k1 }, |
774 | 4.01k | { CF_ECC_CURVE("secp160r1"), NID_secp160r1 }, |
775 | 4.01k | { CF_ECC_CURVE("secp160r2"), NID_secp160r2 }, |
776 | 4.01k | { CF_ECC_CURVE("secp192k1"), NID_secp192k1 }, |
777 | 4.01k | { CF_ECC_CURVE("secp224k1"), NID_secp224k1 }, |
778 | 4.01k | { CF_ECC_CURVE("secp224r1"), NID_secp224r1 }, |
779 | 4.01k | { CF_ECC_CURVE("secp256k1"), NID_secp256k1 }, |
780 | 4.01k | { CF_ECC_CURVE("secp384r1"), NID_secp384r1 }, |
781 | 4.01k | { CF_ECC_CURVE("secp521r1"), NID_secp521r1 }, |
782 | 4.01k | }; |
783 | | |
784 | 4.01k | if ( LUT.find(curveType.Get()) == LUT.end() ) { |
785 | 392 | return std::nullopt; |
786 | 392 | } |
787 | | |
788 | 3.61k | return LUT.at(curveType.Get()); |
789 | 4.01k | } |
790 | | |
791 | 310 | std::optional<bool> wolfCrypt_OpenSSL::OpECC_ValidatePubkey(operation::ECC_ValidatePubkey& op) { |
792 | 310 | std::optional<bool> ret = std::nullopt; |
793 | 310 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
794 | | |
795 | 310 | CF_EC_KEY key(ds); |
796 | 310 | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
797 | | |
798 | 310 | std::unique_ptr<CF_EC_POINT> pub = nullptr; |
799 | | |
800 | 310 | { |
801 | 310 | std::optional<int> curveNID; |
802 | 310 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
803 | 244 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
804 | 244 | group->Lock(); |
805 | 244 | CF_CHECK_NE(group->GetPtr(), nullptr); |
806 | 244 | } |
807 | | |
808 | 244 | CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1); |
809 | | |
810 | | /* Construct key */ |
811 | 244 | CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
812 | 244 | CF_CHECK_TRUE(pub->Set(op.pub.first, op.pub.second)); |
813 | | |
814 | | /* Reject oversized pubkeys until it is fixed in OpenSSL |
815 | | * https://github.com/openssl/openssl/issues/17590 |
816 | | */ |
817 | | #if 0 |
818 | | { |
819 | | const auto order = cryptofuzz::repository::ECC_CurveToOrder(op.curveType.Get()); |
820 | | CF_CHECK_NE(order, std::nullopt); |
821 | | CF_CHECK_TRUE(op.pub.first.IsLessThan(*order)); |
822 | | CF_CHECK_TRUE(op.pub.second.IsLessThan(*order)); |
823 | | } |
824 | | #endif |
825 | | |
826 | 18 | ret = EC_KEY_set_public_key(key.GetPtr(), pub->GetPtr()) == 1; |
827 | 310 | end: |
828 | 310 | return ret; |
829 | 18 | } |
830 | | |
831 | 908 | std::optional<component::ECC_PublicKey> wolfCrypt_OpenSSL::OpECC_PrivateToPublic(operation::ECC_PrivateToPublic& op) { |
832 | 908 | std::optional<component::ECC_PublicKey> ret = std::nullopt; |
833 | 908 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
834 | | |
835 | 908 | char* pub_x_str = nullptr; |
836 | 908 | char* pub_y_str = nullptr; |
837 | | |
838 | 908 | try { |
839 | 908 | CF_EC_KEY key(ds); |
840 | 908 | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
841 | 908 | OpenSSL_bignum::Bignum prv(ds); |
842 | 908 | std::unique_ptr<CF_EC_POINT> pub = nullptr; |
843 | 908 | OpenSSL_bignum::Bignum pub_x(ds); |
844 | 908 | OpenSSL_bignum::Bignum pub_y(ds); |
845 | | |
846 | 908 | { |
847 | 908 | std::optional<int> curveNID; |
848 | 908 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
849 | 796 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
850 | 796 | group->Lock(); |
851 | 796 | CF_CHECK_NE(group->GetPtr(), nullptr); |
852 | 796 | } |
853 | | |
854 | 796 | CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1); |
855 | | |
856 | | /* Load private key */ |
857 | 796 | CF_CHECK_EQ(prv.Set(op.priv.ToString(ds)), true); |
858 | | |
859 | | /* Set private key */ |
860 | 769 | CF_CHECK_EQ(EC_KEY_set_private_key(key.GetPtr(), prv.GetPtr()), 1); |
861 | | |
862 | | /* Compute public key */ |
863 | 701 | CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
864 | 701 | CF_CHECK_EQ(EC_POINT_mul(group->GetPtr(), pub->GetPtr(), prv.GetPtr(), nullptr, nullptr, nullptr), 1); |
865 | | |
866 | 663 | CF_CHECK_EQ(pub_x.New(), true); |
867 | 663 | CF_CHECK_EQ(pub_y.New(), true); |
868 | | |
869 | 663 | CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), pub->GetPtr(), pub_x.GetDestPtr(), pub_y.GetDestPtr(), nullptr), 0); |
870 | | |
871 | | /* Convert bignum x/y to strings */ |
872 | 634 | CF_CHECK_NE(pub_x_str = BN_bn2dec(pub_x.GetPtr()), nullptr); |
873 | 634 | CF_CHECK_NE(pub_y_str = BN_bn2dec(pub_y.GetPtr()), nullptr); |
874 | | |
875 | | /* Save bignum x/y */ |
876 | 634 | ret = { std::string(pub_x_str), std::string(pub_y_str) }; |
877 | 634 | } catch ( ... ) { } |
878 | | |
879 | 908 | end: |
880 | 908 | OPENSSL_free(pub_x_str); |
881 | 908 | OPENSSL_free(pub_y_str); |
882 | | |
883 | 908 | return ret; |
884 | 908 | } |
885 | | |
886 | 175 | std::optional<component::ECC_Point> wolfCrypt_OpenSSL::OpECC_Point_Add(operation::ECC_Point_Add& op) { |
887 | 175 | std::optional<component::ECC_Point> ret = std::nullopt; |
888 | 175 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
889 | | |
890 | 175 | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
891 | 175 | std::unique_ptr<CF_EC_POINT> a = nullptr, b = nullptr, res = nullptr; |
892 | 175 | char* x_str = nullptr; |
893 | 175 | char* y_str = nullptr; |
894 | | |
895 | 175 | { |
896 | 175 | std::optional<int> curveNID; |
897 | 175 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
898 | 144 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
899 | 144 | group->Lock(); |
900 | 144 | CF_CHECK_NE(group->GetPtr(), nullptr); |
901 | 144 | } |
902 | | |
903 | 144 | CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
904 | 144 | CF_CHECK_TRUE(a->Set(op.a.first, op.a.second)); |
905 | | |
906 | 91 | CF_CHECK_NE(b = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
907 | 91 | CF_CHECK_TRUE(b->Set(op.b.first, op.b.second)); |
908 | | |
909 | 68 | CF_CHECK_NE(res = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
910 | | |
911 | 68 | CF_CHECK_NE(EC_POINT_add(group->GetPtr(), res->GetPtr(), a->GetPtr(), b->GetPtr(), nullptr), 0); |
912 | | |
913 | 68 | { |
914 | 68 | OpenSSL_bignum::Bignum x(ds); |
915 | 68 | OpenSSL_bignum::Bignum y(ds); |
916 | | |
917 | 68 | CF_CHECK_EQ(x.New(), true); |
918 | 68 | CF_CHECK_EQ(y.New(), true); |
919 | | |
920 | 68 | CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), res->GetPtr(), x.GetDestPtr(), y.GetDestPtr(), nullptr), 0); |
921 | | |
922 | | /* Convert bignum x/y to strings */ |
923 | 64 | CF_CHECK_NE(x_str = BN_bn2dec(x.GetPtr()), nullptr); |
924 | 64 | CF_CHECK_NE(y_str = BN_bn2dec(y.GetPtr()), nullptr); |
925 | | |
926 | 64 | ret = { std::string(x_str), std::string(y_str) }; |
927 | 64 | } |
928 | | |
929 | 175 | end: |
930 | 175 | OPENSSL_free(x_str); |
931 | 175 | OPENSSL_free(y_str); |
932 | | |
933 | 175 | return ret; |
934 | 64 | } |
935 | | |
936 | 258 | std::optional<component::ECC_Point> wolfCrypt_OpenSSL::OpECC_Point_Mul(operation::ECC_Point_Mul& op) { |
937 | 258 | std::optional<component::ECC_Point> ret = std::nullopt; |
938 | 258 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
939 | | |
940 | 258 | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
941 | 258 | std::unique_ptr<CF_EC_POINT> a = nullptr, res = nullptr; |
942 | 258 | OpenSSL_bignum::Bignum b(ds); |
943 | 258 | char* x_str = nullptr; |
944 | 258 | char* y_str = nullptr; |
945 | | |
946 | 258 | { |
947 | 258 | std::optional<int> curveNID; |
948 | 258 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
949 | 211 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
950 | 211 | group->Lock(); |
951 | 211 | CF_CHECK_NE(group->GetPtr(), nullptr); |
952 | 211 | } |
953 | | |
954 | 211 | CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
955 | 211 | CF_CHECK_TRUE(a->Set(op.a.first, op.a.second)); |
956 | | |
957 | 169 | CF_CHECK_NE(res = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
958 | | |
959 | 169 | CF_CHECK_EQ(b.Set(op.b.ToString(ds)), true); |
960 | | |
961 | 159 | CF_CHECK_NE(EC_POINT_mul(group->GetPtr(), res->GetPtr(), nullptr, a->GetPtr(), b.GetPtr(), nullptr), 0); |
962 | | |
963 | 147 | if ( op.b.ToTrimmedString() == "0" ) { |
964 | 10 | CF_ASSERT( |
965 | 10 | EC_POINT_is_at_infinity(group->GetPtr(), res->GetPtr()) == 1, |
966 | 10 | "Point multiplication by 0 does not yield point at infinity"); |
967 | 10 | } |
968 | | |
969 | 147 | { |
970 | 147 | OpenSSL_bignum::BN_CTX ctx(ds); |
971 | | |
972 | 147 | if ( !EC_POINT_is_on_curve(group->GetPtr(), a->GetPtr(), ctx.GetPtr()) ) { |
973 | 0 | CF_ASSERT( |
974 | 0 | EC_POINT_is_on_curve(group->GetPtr(), res->GetPtr(), ctx.GetPtr()) == 0, |
975 | 0 | "Point multiplication of invalid point yields valid point"); |
976 | 0 | } |
977 | 147 | } |
978 | | |
979 | 147 | ret = res->Get(); |
980 | | |
981 | 258 | end: |
982 | 258 | OPENSSL_free(x_str); |
983 | 258 | OPENSSL_free(y_str); |
984 | | |
985 | 258 | return ret; |
986 | 147 | } |
987 | | |
988 | 300 | std::optional<component::ECC_Point> wolfCrypt_OpenSSL::OpECC_Point_Neg(operation::ECC_Point_Neg& op) { |
989 | 300 | std::optional<component::ECC_Point> ret = std::nullopt; |
990 | 300 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
991 | | |
992 | 300 | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
993 | 300 | std::unique_ptr<CF_EC_POINT> a = nullptr, res = nullptr; |
994 | 300 | char* x_str = nullptr; |
995 | 300 | char* y_str = nullptr; |
996 | | |
997 | 300 | { |
998 | 300 | std::optional<int> curveNID; |
999 | 300 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
1000 | 256 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
1001 | 256 | group->Lock(); |
1002 | 256 | CF_CHECK_NE(group->GetPtr(), nullptr); |
1003 | 256 | } |
1004 | | |
1005 | 256 | CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
1006 | 256 | CF_CHECK_TRUE(a->Set(op.a.first, op.a.second)); |
1007 | | |
1008 | 39 | CF_CHECK_NE(EC_POINT_invert(group->GetPtr(), a->GetPtr(), nullptr), 0); |
1009 | | |
1010 | 39 | { |
1011 | 39 | OpenSSL_bignum::Bignum x(ds); |
1012 | 39 | OpenSSL_bignum::Bignum y(ds); |
1013 | | |
1014 | 39 | CF_CHECK_EQ(x.New(), true); |
1015 | 39 | CF_CHECK_EQ(y.New(), true); |
1016 | | |
1017 | 39 | CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), a->GetPtr(), x.GetDestPtr(), y.GetDestPtr(), nullptr), 0); |
1018 | | |
1019 | | /* Convert bignum x/y to strings */ |
1020 | 39 | CF_CHECK_NE(x_str = BN_bn2dec(x.GetPtr()), nullptr); |
1021 | 39 | CF_CHECK_NE(y_str = BN_bn2dec(y.GetPtr()), nullptr); |
1022 | | |
1023 | 39 | ret = { std::string(x_str), std::string(y_str) }; |
1024 | 39 | } |
1025 | | |
1026 | 300 | end: |
1027 | 300 | OPENSSL_free(x_str); |
1028 | 300 | OPENSSL_free(y_str); |
1029 | | |
1030 | 300 | return ret; |
1031 | 39 | } |
1032 | | |
1033 | 126 | std::optional<bool> wolfCrypt_OpenSSL::OpECC_Point_Cmp(operation::ECC_Point_Cmp& op) { |
1034 | 126 | std::optional<bool> ret = std::nullopt; |
1035 | 126 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
1036 | | |
1037 | 126 | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
1038 | 126 | std::unique_ptr<CF_EC_POINT> a = nullptr, b = nullptr; |
1039 | | |
1040 | 126 | { |
1041 | 126 | std::optional<int> curveNID; |
1042 | 126 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
1043 | 85 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
1044 | 85 | group->Lock(); |
1045 | 85 | CF_CHECK_NE(group->GetPtr(), nullptr); |
1046 | 85 | } |
1047 | | |
1048 | 85 | CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
1049 | 85 | CF_CHECK_TRUE(a->Set(op.a.first, op.a.second)); |
1050 | | |
1051 | 62 | CF_CHECK_NE(b = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
1052 | 62 | CF_CHECK_TRUE(b->Set(op.b.first, op.b.second)); |
1053 | | |
1054 | 45 | ret = EC_POINT_cmp(group->GetPtr(), a->GetPtr(), b->GetPtr(), nullptr) == 0; |
1055 | | |
1056 | 126 | end: |
1057 | | |
1058 | 126 | return ret; |
1059 | 45 | } |
1060 | | |
1061 | 1.09k | std::optional<bool> wolfCrypt_OpenSSL::OpECDSA_Verify(operation::ECDSA_Verify& op) { |
1062 | 1.09k | std::optional<bool> ret = std::nullopt; |
1063 | 1.09k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
1064 | | |
1065 | 1.09k | ECDSA_SIG* signature = nullptr; |
1066 | | |
1067 | 1.09k | try { |
1068 | 1.09k | CF_EC_KEY key(ds); |
1069 | 1.09k | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
1070 | | |
1071 | 1.09k | std::unique_ptr<CF_EC_POINT> pub = nullptr; |
1072 | | |
1073 | 1.09k | OpenSSL_bignum::Bignum sig_s(ds); |
1074 | 1.09k | OpenSSL_bignum::Bignum sig_r(ds); |
1075 | | |
1076 | | /* Initialize */ |
1077 | 1.09k | { |
1078 | 1.09k | { |
1079 | 1.09k | std::optional<int> curveNID; |
1080 | 1.09k | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
1081 | 1.05k | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
1082 | 1.05k | group->Lock(); |
1083 | 1.05k | CF_CHECK_NE(group->GetPtr(), nullptr); |
1084 | 1.05k | } |
1085 | 1.05k | CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1); |
1086 | | |
1087 | | /* Construct signature */ |
1088 | 1.05k | CF_CHECK_EQ(sig_r.Set(op.signature.signature.first.ToString(ds)), true); |
1089 | 1.04k | CF_CHECK_EQ(sig_s.Set(op.signature.signature.second.ToString(ds)), true); |
1090 | 1.03k | CF_CHECK_NE(signature = ECDSA_SIG_new(), nullptr); |
1091 | 1.03k | CF_CHECK_EQ(ECDSA_SIG_set0(signature, sig_r.GetDestPtr(false), sig_s.GetDestPtr(false)), 1); |
1092 | | /* 'signature' now has ownership, and the BIGNUMs will be freed by ECDSA_SIG_free */ |
1093 | 1.03k | sig_r.ReleaseOwnership(); |
1094 | 1.03k | sig_s.ReleaseOwnership(); |
1095 | | |
1096 | | /* Construct key */ |
1097 | 1.03k | CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
1098 | 1.03k | CF_CHECK_TRUE(pub->Set(op.signature.pub.first, op.signature.pub.second)); |
1099 | 1.01k | CF_CHECK_EQ(EC_KEY_set_public_key(key.GetPtr(), pub->GetPtr()), 1); |
1100 | 1.01k | } |
1101 | | |
1102 | | /* Process */ |
1103 | 0 | { |
1104 | 1.01k | int res; |
1105 | 1.01k | if ( op.digestType.Get() == CF_DIGEST("NULL") ) { |
1106 | | //const auto CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType); |
1107 | 842 | const auto CT = op.cleartext; |
1108 | 842 | res = ECDSA_do_verify(CT.GetPtr(), CT.GetSize(), signature, key.GetPtr()); |
1109 | 842 | } else if ( op.digestType.Get() == CF_DIGEST("SHA256") ) { |
1110 | 66 | uint8_t CT[32]; |
1111 | 66 | SHA256(op.cleartext.GetPtr(), op.cleartext.GetSize(), CT); |
1112 | 66 | res = ECDSA_do_verify(CT, sizeof(CT), signature, key.GetPtr()); |
1113 | 107 | } else { |
1114 | | /* TODO other digests */ |
1115 | 107 | goto end; |
1116 | 107 | } |
1117 | | |
1118 | 908 | if ( res == 0 ) { |
1119 | 96 | ret = false; |
1120 | 812 | } else if ( res == 1 ) { |
1121 | 724 | ret = true; |
1122 | 724 | } else { |
1123 | | /* ECDSA_do_verify failed -- don't set ret */ |
1124 | 88 | } |
1125 | | |
1126 | 908 | } |
1127 | 908 | } catch ( ... ) { } |
1128 | | |
1129 | 1.09k | end: |
1130 | 1.09k | if ( signature != nullptr ) { |
1131 | 1.03k | ECDSA_SIG_free(signature); |
1132 | 1.03k | } |
1133 | | |
1134 | 1.09k | return ret; |
1135 | 1.09k | } |
1136 | | |
1137 | 1.00k | std::optional<component::ECDSA_Signature> wolfCrypt_OpenSSL::OpECDSA_Sign(operation::ECDSA_Sign& op) { |
1138 | 1.00k | std::optional<component::ECDSA_Signature> ret = std::nullopt; |
1139 | 1.00k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
1140 | | |
1141 | 1.00k | ECDSA_SIG* signature = nullptr; |
1142 | 1.00k | char* pub_x_str = nullptr; |
1143 | 1.00k | char* pub_y_str = nullptr; |
1144 | 1.00k | char* sig_r_str = nullptr; |
1145 | 1.00k | char* sig_s_str = nullptr; |
1146 | | |
1147 | 1.00k | try { |
1148 | 1.00k | CF_EC_KEY key(ds); |
1149 | 1.00k | std::shared_ptr<CF_EC_GROUP> group = nullptr; |
1150 | 1.00k | OpenSSL_bignum::Bignum prv(ds); |
1151 | 1.00k | std::unique_ptr<CF_EC_POINT> pub = nullptr; |
1152 | 1.00k | OpenSSL_bignum::Bignum pub_x(ds); |
1153 | 1.00k | OpenSSL_bignum::Bignum pub_y(ds); |
1154 | 1.00k | const BIGNUM *R = nullptr, *S = nullptr; |
1155 | | |
1156 | 1.00k | CF_CHECK_TRUE(op.UseRandomNonce()); |
1157 | 962 | CF_CHECK_TRUE(op.digestType.Is(CF_DIGEST("NULL"))); |
1158 | | |
1159 | 843 | { |
1160 | 843 | std::optional<int> curveNID; |
1161 | 843 | CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt); |
1162 | 832 | CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr); |
1163 | 832 | group->Lock(); |
1164 | 832 | CF_CHECK_NE(group->GetPtr(), nullptr); |
1165 | 832 | } |
1166 | | |
1167 | 832 | CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1); |
1168 | | |
1169 | | /* Load private key */ |
1170 | 832 | CF_CHECK_EQ(prv.Set(op.priv.ToString(ds)), true); |
1171 | | |
1172 | | /* Set private key */ |
1173 | 822 | CF_CHECK_EQ(EC_KEY_set_private_key(key.GetPtr(), prv.GetPtr()), 1); |
1174 | | |
1175 | | /* Compute public key */ |
1176 | 807 | CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr); |
1177 | 807 | CF_CHECK_EQ(EC_POINT_mul(group->GetPtr(), pub->GetPtr(), prv.GetPtr(), nullptr, nullptr, nullptr), 1); |
1178 | | |
1179 | 796 | CF_CHECK_EQ(pub_x.New(), true); |
1180 | 796 | CF_CHECK_EQ(pub_y.New(), true); |
1181 | | |
1182 | 796 | CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), pub->GetPtr(), pub_x.GetDestPtr(), pub_y.GetDestPtr(), nullptr), 0); |
1183 | | |
1184 | 781 | CF_CHECK_NE(pub_x_str = BN_bn2dec(pub_x.GetPtr()), nullptr); |
1185 | 781 | CF_CHECK_NE(pub_y_str = BN_bn2dec(pub_y.GetPtr()), nullptr); |
1186 | | |
1187 | 781 | const auto CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType); |
1188 | | |
1189 | 781 | CF_CHECK_NE(signature = ECDSA_do_sign(CT.GetPtr(), CT.GetSize(), key.GetPtr()), nullptr); |
1190 | | |
1191 | 727 | /* noret */ ECDSA_SIG_get0(signature, &R, &S); |
1192 | 727 | CF_CHECK_NE(R, nullptr); |
1193 | 727 | CF_CHECK_NE(S, nullptr); |
1194 | | |
1195 | | /* Convert bignum x/y to strings */ |
1196 | 727 | CF_CHECK_NE(sig_r_str = BN_bn2dec(R), nullptr); |
1197 | 727 | CF_CHECK_NE(sig_s_str = BN_bn2dec(S), nullptr); |
1198 | | |
1199 | | |
1200 | 727 | component::Bignum S_corrected{std::string(sig_s_str)}; |
1201 | 727 | CF_NORET(util::AdjustECDSASignature(op.curveType.Get(), S_corrected)); |
1202 | | |
1203 | 727 | ret = { {sig_r_str, S_corrected.ToTrimmedString()}, {pub_x_str, pub_y_str} }; |
1204 | 727 | } catch ( ... ) { } |
1205 | | |
1206 | 1.00k | end: |
1207 | 1.00k | if ( signature != nullptr ) { |
1208 | 727 | ECDSA_SIG_free(signature); |
1209 | 727 | } |
1210 | 1.00k | OPENSSL_free(pub_x_str); |
1211 | 1.00k | OPENSSL_free(pub_y_str); |
1212 | 1.00k | OPENSSL_free(sig_r_str); |
1213 | 1.00k | OPENSSL_free(sig_s_str); |
1214 | | |
1215 | 1.00k | return ret; |
1216 | 1.00k | } |
1217 | | |
1218 | 3.57k | std::optional<component::Bignum> wolfCrypt_OpenSSL::OpBignumCalc(operation::BignumCalc& op) { |
1219 | 3.57k | std::optional<component::Bignum> ret = std::nullopt; |
1220 | 3.57k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
1221 | | |
1222 | 3.57k | OpenSSL_bignum::BN_CTX ctx(ds); |
1223 | 3.57k | OpenSSL_bignum::BignumCluster bn(ds, |
1224 | 3.57k | OpenSSL_bignum::Bignum(ds), |
1225 | 3.57k | OpenSSL_bignum::Bignum(ds), |
1226 | 3.57k | OpenSSL_bignum::Bignum(ds), |
1227 | 3.57k | OpenSSL_bignum::Bignum(ds)); |
1228 | 3.57k | OpenSSL_bignum::Bignum res(ds); |
1229 | 3.57k | std::unique_ptr<OpenSSL_bignum::Operation> opRunner = nullptr; |
1230 | | |
1231 | 3.57k | CF_CHECK_EQ(res.New(), true); |
1232 | 3.57k | CF_CHECK_EQ(bn.New(0), true); |
1233 | 3.57k | CF_CHECK_EQ(bn.New(1), true); |
1234 | 3.57k | CF_CHECK_EQ(bn.New(2), true); |
1235 | 3.57k | CF_CHECK_EQ(bn.New(3), true); |
1236 | | |
1237 | 3.57k | CF_CHECK_EQ(res.Set("0"), true); |
1238 | 3.57k | CF_CHECK_EQ(bn.Set(0, op.bn0.ToString(ds)), true); |
1239 | 3.55k | CF_CHECK_EQ(bn.Set(1, op.bn1.ToString(ds)), true); |
1240 | 3.54k | CF_CHECK_EQ(bn.Set(2, op.bn2.ToString(ds)), true); |
1241 | 3.52k | CF_CHECK_EQ(bn.Set(3, op.bn3.ToString(ds)), true); |
1242 | | |
1243 | 3.51k | switch ( op.calcOp.Get() ) { |
1244 | 26 | case CF_CALCOP("Add(A,B)"): |
1245 | 26 | opRunner = std::make_unique<OpenSSL_bignum::Add>(); |
1246 | 26 | break; |
1247 | 34 | case CF_CALCOP("Sub(A,B)"): |
1248 | 34 | opRunner = std::make_unique<OpenSSL_bignum::Sub>(); |
1249 | 34 | break; |
1250 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1251 | | case CF_CALCOP("Mul(A,B)"): |
1252 | | opRunner = std::make_unique<OpenSSL_bignum::Mul>(); |
1253 | | break; |
1254 | | #endif |
1255 | 49 | case CF_CALCOP("Mod(A,B)"): |
1256 | 49 | opRunner = std::make_unique<OpenSSL_bignum::Mod>(); |
1257 | 49 | break; |
1258 | 396 | case CF_CALCOP("ExpMod(A,B,C)"): |
1259 | 396 | opRunner = std::make_unique<OpenSSL_bignum::ExpMod>(); |
1260 | 396 | break; |
1261 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1262 | | case CF_CALCOP("Sqr(A)"): |
1263 | | opRunner = std::make_unique<OpenSSL_bignum::Sqr>(); |
1264 | | break; |
1265 | | #endif |
1266 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1267 | | case CF_CALCOP("GCD(A,B)"): |
1268 | | opRunner = std::make_unique<OpenSSL_bignum::GCD>(); |
1269 | | break; |
1270 | | #endif |
1271 | 62 | case CF_CALCOP("AddMod(A,B,C)"): |
1272 | 62 | opRunner = std::make_unique<OpenSSL_bignum::AddMod>(); |
1273 | 62 | break; |
1274 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1275 | | case CF_CALCOP("SubMod(A,B,C)"): |
1276 | | opRunner = std::make_unique<OpenSSL_bignum::SubMod>(); |
1277 | | break; |
1278 | | #endif |
1279 | 58 | case CF_CALCOP("MulMod(A,B,C)"): |
1280 | 58 | opRunner = std::make_unique<OpenSSL_bignum::MulMod>(); |
1281 | 58 | break; |
1282 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1283 | | case CF_CALCOP("SqrMod(A,B)"): |
1284 | | opRunner = std::make_unique<OpenSSL_bignum::SqrMod>(); |
1285 | | break; |
1286 | | #endif |
1287 | 276 | case CF_CALCOP("InvMod(A,B)"): |
1288 | 276 | opRunner = std::make_unique<OpenSSL_bignum::InvMod>(); |
1289 | 276 | break; |
1290 | 35 | case CF_CALCOP("Cmp(A,B)"): |
1291 | 35 | opRunner = std::make_unique<OpenSSL_bignum::Cmp>(); |
1292 | 35 | break; |
1293 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1294 | | case CF_CALCOP("Div(A,B)"): |
1295 | | opRunner = std::make_unique<OpenSSL_bignum::Div>(); |
1296 | | break; |
1297 | | #endif |
1298 | 12 | case CF_CALCOP("IsPrime(A)"): |
1299 | 12 | opRunner = std::make_unique<OpenSSL_bignum::IsPrime>(); |
1300 | 12 | break; |
1301 | 12 | case CF_CALCOP("Sqrt(A)"): |
1302 | 12 | opRunner = std::make_unique<OpenSSL_bignum::Sqrt>(); |
1303 | 12 | break; |
1304 | 9 | case CF_CALCOP("IsNeg(A)"): |
1305 | 9 | opRunner = std::make_unique<OpenSSL_bignum::IsNeg>(); |
1306 | 9 | break; |
1307 | 10 | case CF_CALCOP("IsEq(A,B)"): |
1308 | 10 | opRunner = std::make_unique<OpenSSL_bignum::IsEq>(); |
1309 | 10 | break; |
1310 | 16 | case CF_CALCOP("IsEven(A)"): |
1311 | 16 | opRunner = std::make_unique<OpenSSL_bignum::IsEven>(); |
1312 | 16 | break; |
1313 | 12 | case CF_CALCOP("IsOdd(A)"): |
1314 | 12 | opRunner = std::make_unique<OpenSSL_bignum::IsOdd>(); |
1315 | 12 | break; |
1316 | 37 | case CF_CALCOP("IsZero(A)"): |
1317 | 37 | opRunner = std::make_unique<OpenSSL_bignum::IsZero>(); |
1318 | 37 | break; |
1319 | 32 | case CF_CALCOP("IsOne(A)"): |
1320 | 32 | opRunner = std::make_unique<OpenSSL_bignum::IsOne>(); |
1321 | 32 | break; |
1322 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1323 | | case CF_CALCOP("Jacobi(A,B)"): |
1324 | | opRunner = std::make_unique<OpenSSL_bignum::Jacobi>(); |
1325 | | break; |
1326 | | #endif |
1327 | | #if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1328 | | case CF_CALCOP("Mod_NIST_192(A)"): |
1329 | | opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_192>(); |
1330 | | break; |
1331 | | case CF_CALCOP("Mod_NIST_224(A)"): |
1332 | | opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_224>(); |
1333 | | break; |
1334 | | case CF_CALCOP("Mod_NIST_256(A)"): |
1335 | | opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_256>(); |
1336 | | break; |
1337 | | case CF_CALCOP("Mod_NIST_384(A)"): |
1338 | | opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_384>(); |
1339 | | break; |
1340 | | case CF_CALCOP("Mod_NIST_521(A)"): |
1341 | | opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_521>(); |
1342 | | break; |
1343 | | #endif |
1344 | 11 | case CF_CALCOP("SqrtMod(A,B)"): |
1345 | 11 | opRunner = std::make_unique<OpenSSL_bignum::SqrtMod>(); |
1346 | 11 | break; |
1347 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
1348 | | case CF_CALCOP("LCM(A,B)"): |
1349 | | opRunner = std::make_unique<OpenSSL_bignum::LCM>(); |
1350 | | break; |
1351 | | #endif |
1352 | 10 | case CF_CALCOP("Exp(A,B)"): |
1353 | 10 | opRunner = std::make_unique<OpenSSL_bignum::Exp>(); |
1354 | 10 | break; |
1355 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1356 | | case CF_CALCOP("Abs(A)"): |
1357 | | opRunner = std::make_unique<OpenSSL_bignum::Abs>(); |
1358 | | break; |
1359 | | #endif |
1360 | 26 | case CF_CALCOP("RShift(A,B)"): |
1361 | 26 | opRunner = std::make_unique<OpenSSL_bignum::RShift>(); |
1362 | 26 | break; |
1363 | 6 | case CF_CALCOP("LShift1(A)"): |
1364 | 6 | opRunner = std::make_unique<OpenSSL_bignum::LShift1>(); |
1365 | 6 | break; |
1366 | 14 | case CF_CALCOP("SetBit(A,B)"): |
1367 | 14 | opRunner = std::make_unique<OpenSSL_bignum::SetBit>(); |
1368 | 14 | break; |
1369 | 10 | case CF_CALCOP("ClearBit(A,B)"): |
1370 | 10 | opRunner = std::make_unique<OpenSSL_bignum::ClearBit>(); |
1371 | 10 | break; |
1372 | 24 | case CF_CALCOP("Bit(A,B)"): |
1373 | 24 | opRunner = std::make_unique<OpenSSL_bignum::Bit>(); |
1374 | 24 | break; |
1375 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1376 | | case CF_CALCOP("CmpAbs(A,B)"): |
1377 | | opRunner = std::make_unique<OpenSSL_bignum::CmpAbs>(); |
1378 | | break; |
1379 | | #endif |
1380 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
1381 | | case CF_CALCOP("ModLShift(A,B,C)"): |
1382 | | opRunner = std::make_unique<OpenSSL_bignum::ModLShift>(); |
1383 | | break; |
1384 | | #endif |
1385 | 10 | case CF_CALCOP("IsPow2(A)"): |
1386 | 10 | opRunner = std::make_unique<OpenSSL_bignum::IsPow2>(); |
1387 | 10 | break; |
1388 | 12 | case CF_CALCOP("Mask(A,B)"): |
1389 | 12 | opRunner = std::make_unique<OpenSSL_bignum::Mask>(); |
1390 | 12 | break; |
1391 | 3.51k | } |
1392 | | |
1393 | 3.51k | CF_CHECK_NE(opRunner, nullptr); |
1394 | 1.19k | CF_CHECK_EQ(opRunner->Run(ds, res, bn, ctx), true); |
1395 | | |
1396 | 743 | ret = res.ToComponentBignum(); |
1397 | | |
1398 | 3.54k | end: |
1399 | 3.54k | return ret; |
1400 | 743 | } |
1401 | | |
1402 | | } /* namespace module */ |
1403 | | } /* namespace cryptofuzz */ |