/src/cryptofuzz/modules/libsodium/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 <sodium.h> |
5 | | |
6 | | namespace cryptofuzz { |
7 | | namespace module { |
8 | | |
9 | | libsodium::libsodium(void) : |
10 | 10 | Module("libsodium") { |
11 | 10 | if ( sodium_init() == -1 ) { |
12 | 0 | abort(); |
13 | 0 | } |
14 | 10 | } |
15 | | |
16 | 103 | std::optional<component::Digest> libsodium::SHA256(operation::Digest& op) const { |
17 | 103 | std::optional<component::Digest> ret = std::nullopt; |
18 | | |
19 | 103 | uint8_t out[crypto_hash_sha256_BYTES]; |
20 | | |
21 | 103 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
22 | | |
23 | 103 | bool doMulti = false; |
24 | 103 | try { |
25 | 103 | doMulti = ds.Get<bool>(); |
26 | 103 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
27 | 18 | } |
28 | | |
29 | 103 | if ( doMulti == false ) { |
30 | 60 | crypto_hash_sha256(out, op.cleartext.GetPtr(), op.cleartext.GetSize()); |
31 | | |
32 | 60 | ret = component::Digest(out, crypto_hash_sha256_BYTES); |
33 | 60 | } else { |
34 | 43 | crypto_hash_sha256_state state; |
35 | | |
36 | 43 | util::Multipart parts; |
37 | | |
38 | | /* Initialize */ |
39 | 43 | { |
40 | 43 | CF_CHECK_EQ(crypto_hash_sha256_init(&state), 0); |
41 | 43 | parts = util::ToParts(ds, op.cleartext); |
42 | 43 | } |
43 | | |
44 | | /* Process */ |
45 | 8.49k | for (const auto& part : parts) { |
46 | 8.49k | CF_CHECK_EQ(crypto_hash_sha256_update(&state, part.first, part.second), 0); |
47 | 8.49k | } |
48 | | |
49 | | /* Finalize */ |
50 | 43 | { |
51 | 43 | CF_CHECK_EQ(crypto_hash_sha256_final(&state, out), 0); |
52 | 43 | } |
53 | | |
54 | 43 | ret = component::Digest(out, crypto_hash_sha256_BYTES); |
55 | 43 | } |
56 | | |
57 | 103 | end: |
58 | | |
59 | 103 | return ret; |
60 | 103 | } |
61 | | |
62 | 103 | std::optional<component::Digest> libsodium::SHA512(operation::Digest& op) const { |
63 | 103 | std::optional<component::Digest> ret = std::nullopt; |
64 | | |
65 | 103 | uint8_t out[crypto_hash_sha512_BYTES]; |
66 | | |
67 | 103 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
68 | | |
69 | 103 | bool doMulti = false; |
70 | 103 | try { |
71 | 103 | doMulti = ds.Get<bool>(); |
72 | 103 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
73 | 26 | } |
74 | | |
75 | 103 | if ( doMulti == false ) { |
76 | 62 | crypto_hash_sha512(out, op.cleartext.GetPtr(), op.cleartext.GetSize()); |
77 | | |
78 | 62 | ret = component::Digest(out, crypto_hash_sha512_BYTES); |
79 | 62 | } else { |
80 | 41 | crypto_hash_sha512_state state; |
81 | | |
82 | 41 | util::Multipart parts; |
83 | | |
84 | | /* Initialize */ |
85 | 41 | { |
86 | 41 | CF_CHECK_EQ(crypto_hash_sha512_init(&state), 0); |
87 | 41 | parts = util::ToParts(ds, op.cleartext); |
88 | 41 | } |
89 | | |
90 | | /* Process */ |
91 | 11.0k | for (const auto& part : parts) { |
92 | 11.0k | CF_CHECK_EQ(crypto_hash_sha512_update(&state, part.first, part.second), 0); |
93 | 11.0k | } |
94 | | |
95 | | /* Finalize */ |
96 | 41 | { |
97 | 41 | CF_CHECK_EQ(crypto_hash_sha512_final(&state, out), 0); |
98 | 41 | } |
99 | | |
100 | 41 | ret = component::Digest(out, crypto_hash_sha512_BYTES); |
101 | 41 | } |
102 | | |
103 | 103 | end: |
104 | | |
105 | 103 | return ret; |
106 | 103 | } |
107 | | |
108 | 3.42k | std::optional<component::Digest> libsodium::OpDigest(operation::Digest& op) { |
109 | 3.42k | switch ( op.digestType.Get() ) { |
110 | 103 | case CF_DIGEST("SHA256"): |
111 | 103 | return SHA256(op); |
112 | 103 | case CF_DIGEST("SHA512"): |
113 | 103 | return SHA512(op); |
114 | 3.21k | default: |
115 | 3.21k | return std::nullopt; |
116 | 3.42k | } |
117 | 3.42k | } |
118 | | |
119 | 87 | std::optional<component::MAC> libsodium::HMAC_SHA256(operation::HMAC& op) const { |
120 | 87 | std::optional<component::MAC> ret = std::nullopt; |
121 | | |
122 | 87 | uint8_t out[crypto_auth_hmacsha256_BYTES]; |
123 | | |
124 | 87 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
125 | | |
126 | 87 | bool doMulti = false; |
127 | 87 | try { |
128 | 87 | doMulti = ds.Get<bool>(); |
129 | 87 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
130 | 28 | } |
131 | | |
132 | 87 | if ( doMulti == false ) { |
133 | 53 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_auth_hmacsha256_KEYBYTES); |
134 | 3 | CF_CHECK_EQ(crypto_auth_hmacsha256(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.key.GetPtr()), 0); |
135 | | |
136 | 3 | ret = component::MAC(out, crypto_auth_hmacsha256_BYTES); |
137 | 34 | } else { |
138 | 34 | crypto_auth_hmacsha256_state state; |
139 | | |
140 | 34 | util::Multipart parts; |
141 | | |
142 | | /* Initialize */ |
143 | 34 | { |
144 | 34 | CF_CHECK_EQ(crypto_auth_hmacsha256_init(&state, op.cipher.key.GetPtr(), op.cipher.key.GetSize()), 0); |
145 | 34 | parts = util::ToParts(ds, op.cleartext); |
146 | 34 | } |
147 | | |
148 | | /* Process */ |
149 | 7.82k | for (const auto& part : parts) { |
150 | 7.82k | CF_CHECK_EQ(crypto_auth_hmacsha256_update(&state, part.first, part.second), 0); |
151 | 7.82k | } |
152 | | |
153 | | /* Finalize */ |
154 | 34 | { |
155 | 34 | CF_CHECK_EQ(crypto_auth_hmacsha256_final(&state, out), 0); |
156 | 34 | } |
157 | | |
158 | 34 | ret = component::MAC(out, crypto_auth_hmacsha256_BYTES); |
159 | 34 | } |
160 | | |
161 | 87 | end: |
162 | | |
163 | 87 | return ret; |
164 | 87 | } |
165 | | |
166 | 105 | std::optional<component::MAC> libsodium::HMAC_SHA512(operation::HMAC& op) const { |
167 | 105 | std::optional<component::MAC> ret = std::nullopt; |
168 | | |
169 | 105 | uint8_t out[crypto_auth_hmacsha512_BYTES]; |
170 | | |
171 | 105 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
172 | | |
173 | 105 | bool doMulti = false; |
174 | 105 | try { |
175 | 105 | doMulti = ds.Get<bool>(); |
176 | 105 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
177 | 23 | } |
178 | | |
179 | 105 | if ( doMulti == false ) { |
180 | 60 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_auth_hmacsha512_KEYBYTES); |
181 | 1 | CF_CHECK_EQ(crypto_auth_hmacsha512(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.key.GetPtr()), 0); |
182 | | |
183 | 1 | ret = component::MAC(out, crypto_auth_hmacsha512_BYTES); |
184 | 45 | } else { |
185 | 45 | crypto_auth_hmacsha512_state state; |
186 | | |
187 | 45 | util::Multipart parts; |
188 | | |
189 | | /* Initialize */ |
190 | 45 | { |
191 | 45 | CF_CHECK_EQ(crypto_auth_hmacsha512_init(&state, op.cipher.key.GetPtr(), op.cipher.key.GetSize()), 0); |
192 | 45 | parts = util::ToParts(ds, op.cleartext); |
193 | 45 | } |
194 | | |
195 | | /* Process */ |
196 | 9.16k | for (const auto& part : parts) { |
197 | 9.16k | CF_CHECK_EQ(crypto_auth_hmacsha512_update(&state, part.first, part.second), 0); |
198 | 9.16k | } |
199 | | |
200 | | /* Finalize */ |
201 | 45 | { |
202 | 45 | CF_CHECK_EQ(crypto_auth_hmacsha512_final(&state, out), 0); |
203 | 45 | } |
204 | | |
205 | 45 | ret = component::MAC(out, crypto_auth_hmacsha512_BYTES); |
206 | 45 | } |
207 | | |
208 | 105 | end: |
209 | | |
210 | 105 | return ret; |
211 | 105 | } |
212 | | |
213 | 63 | std::optional<component::MAC> libsodium::HMAC_SHA512256(operation::HMAC& op) const { |
214 | 63 | std::optional<component::MAC> ret = std::nullopt; |
215 | | |
216 | 63 | uint8_t out[crypto_auth_hmacsha512256_BYTES]; |
217 | | |
218 | 63 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
219 | | |
220 | 63 | bool doMulti = false; |
221 | 63 | try { |
222 | 63 | doMulti = ds.Get<bool>(); |
223 | 63 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
224 | 19 | } |
225 | | |
226 | 63 | if ( doMulti == false ) { |
227 | 38 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_auth_hmacsha512256_KEYBYTES); |
228 | 2 | CF_CHECK_EQ(crypto_auth_hmacsha512256(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.key.GetPtr()), 0); |
229 | | |
230 | | //ret = component::MAC(out, crypto_auth_hmacsha512256_BYTES); |
231 | 25 | } else { |
232 | 25 | crypto_auth_hmacsha512256_state state; |
233 | | |
234 | 25 | util::Multipart parts; |
235 | | |
236 | | /* Initialize */ |
237 | 25 | { |
238 | 25 | CF_CHECK_EQ(crypto_auth_hmacsha512256_init(&state, op.cipher.key.GetPtr(), op.cipher.key.GetSize()), 0); |
239 | 25 | parts = util::ToParts(ds, op.cleartext); |
240 | 25 | } |
241 | | |
242 | | /* Process */ |
243 | 7.96k | for (const auto& part : parts) { |
244 | 7.96k | CF_CHECK_EQ(crypto_auth_hmacsha512256_update(&state, part.first, part.second), 0); |
245 | 7.96k | } |
246 | | |
247 | | /* Finalize */ |
248 | 25 | { |
249 | 25 | CF_CHECK_EQ(crypto_auth_hmacsha512256_final(&state, out), 0); |
250 | 25 | } |
251 | | |
252 | | //ret = component::MAC(out, crypto_auth_hmacsha512256_BYTES); |
253 | 25 | } |
254 | | |
255 | 63 | end: |
256 | | |
257 | 63 | return ret; |
258 | 63 | } |
259 | | |
260 | 19 | std::optional<component::MAC> libsodium::SIPHASH64(operation::HMAC& op) const { |
261 | 19 | std::optional<component::MAC> ret = std::nullopt; |
262 | 19 | uint8_t out[crypto_shorthash_BYTES]; |
263 | | |
264 | | /* Initialize */ |
265 | 19 | { |
266 | 19 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_shorthash_KEYBYTES); |
267 | 5 | } |
268 | | |
269 | | /* Process */ |
270 | 0 | { |
271 | 5 | CF_CHECK_EQ(crypto_shorthash(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.key.GetPtr()), 0); |
272 | 5 | } |
273 | | |
274 | | /* Finalize */ |
275 | 0 | { |
276 | 5 | ret = component::MAC(out, crypto_shorthash_BYTES); |
277 | 5 | } |
278 | | |
279 | 19 | end: |
280 | | |
281 | 19 | return ret; |
282 | 5 | } |
283 | | |
284 | 16 | std::optional<component::MAC> libsodium::SIPHASH128(operation::HMAC& op) const { |
285 | 16 | std::optional<component::MAC> ret = std::nullopt; |
286 | 16 | uint8_t out[crypto_shorthash_siphashx24_BYTES]; |
287 | | |
288 | | /* Initialize */ |
289 | 16 | { |
290 | 16 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_shorthash_siphashx24_KEYBYTES); |
291 | 7 | } |
292 | | |
293 | | /* Process */ |
294 | 0 | { |
295 | 7 | CF_CHECK_EQ(crypto_shorthash_siphashx24(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.key.GetPtr()), 0); |
296 | 7 | } |
297 | | |
298 | | /* Finalize */ |
299 | 0 | { |
300 | 7 | ret = component::MAC(out, crypto_shorthash_siphashx24_BYTES); |
301 | 7 | } |
302 | | |
303 | 16 | end: |
304 | | |
305 | 16 | return ret; |
306 | 7 | } |
307 | | |
308 | 2.22k | std::optional<component::MAC> libsodium::OpHMAC(operation::HMAC& op) { |
309 | 2.22k | switch ( op.digestType.Get() ) { |
310 | 87 | case CF_DIGEST("SHA256"): |
311 | 87 | return HMAC_SHA256(op); |
312 | 105 | case CF_DIGEST("SHA512"): |
313 | 105 | return HMAC_SHA512(op); |
314 | 63 | case CF_DIGEST("SHA512-256"): |
315 | 63 | return HMAC_SHA512256(op); |
316 | 19 | case CF_DIGEST("SIPHASH64"): |
317 | 19 | return SIPHASH64(op); |
318 | 16 | case CF_DIGEST("SIPHASH128"): |
319 | 16 | return SIPHASH128(op); |
320 | 1.93k | default: |
321 | 1.93k | return std::nullopt; |
322 | 2.22k | } |
323 | 2.22k | } |
324 | | |
325 | 1.10k | std::optional<component::Key> libsodium::OpKDF_HKDF(operation::KDF_HKDF& op) { |
326 | 1.10k | std::optional<component::Key> ret = std::nullopt; |
327 | | |
328 | 1.10k | uint8_t* prk = nullptr; |
329 | 1.10k | uint8_t* out = nullptr; |
330 | | |
331 | 1.10k | switch ( op.digestType.Get() ) { |
332 | 28 | case CF_DIGEST("SHA256"): |
333 | 28 | { |
334 | 28 | prk = util::malloc(crypto_kdf_hkdf_sha256_KEYBYTES); |
335 | | |
336 | 28 | CF_CHECK_EQ(crypto_kdf_hkdf_sha256_extract( |
337 | 28 | prk, |
338 | 28 | op.salt.GetPtr(), |
339 | 28 | op.salt.GetSize(), |
340 | 28 | op.password.GetPtr(), |
341 | 28 | op.password.GetSize()), 0); |
342 | | |
343 | 28 | out = util::malloc(op.keySize); |
344 | | |
345 | 28 | CF_CHECK_EQ(crypto_kdf_hkdf_sha256_expand( |
346 | 28 | out, |
347 | 28 | op.keySize, |
348 | 28 | (const char*)(op.info.GetPtr()), |
349 | 28 | op.info.GetSize(), |
350 | 28 | prk), 0); |
351 | 24 | ret = component::Key(out, op.keySize); |
352 | 24 | } |
353 | 0 | break; |
354 | 53 | case CF_DIGEST("SHA512"): |
355 | 53 | { |
356 | 53 | prk = util::malloc(crypto_kdf_hkdf_sha512_KEYBYTES); |
357 | | |
358 | 53 | CF_CHECK_EQ(crypto_kdf_hkdf_sha512_extract( |
359 | 53 | prk, |
360 | 53 | op.salt.GetPtr(), |
361 | 53 | op.salt.GetSize(), |
362 | 53 | op.password.GetPtr(), |
363 | 53 | op.password.GetSize()), 0); |
364 | | |
365 | 53 | out = util::malloc(op.keySize); |
366 | | |
367 | 53 | CF_CHECK_EQ(crypto_kdf_hkdf_sha512_expand( |
368 | 53 | out, |
369 | 53 | op.keySize, |
370 | 53 | (const char*)(op.info.GetPtr()), |
371 | 53 | op.info.GetSize(), |
372 | 53 | prk), 0); |
373 | 52 | ret = component::Key(out, op.keySize); |
374 | 52 | } |
375 | 0 | break; |
376 | 1.02k | default: |
377 | 1.02k | return std::nullopt; |
378 | 1.10k | } |
379 | | |
380 | 81 | end: |
381 | 81 | util::free(prk); |
382 | 81 | util::free(out); |
383 | | |
384 | 81 | return ret; |
385 | 1.10k | } |
386 | | |
387 | | namespace libsodium_detail { |
388 | | |
389 | | template <size_t TAGLEN, size_t IVLEN, size_t KEYLEN> |
390 | | class AEAD { |
391 | | private: |
392 | | virtual int encrypt(unsigned char *c, |
393 | | unsigned long long *clen, |
394 | | const unsigned char *m, |
395 | | unsigned long long mlen, |
396 | | const unsigned char *ad, |
397 | | unsigned long long adlen, |
398 | | const unsigned char *nsec, |
399 | | const unsigned char *npub, |
400 | | const unsigned char *k) const = 0; |
401 | | virtual int decrypt(unsigned char *m, |
402 | | unsigned long long *mlen, |
403 | | unsigned char *nsec, |
404 | | const unsigned char *c, |
405 | | unsigned long long clen, |
406 | | const unsigned char *ad, |
407 | | unsigned long long adlen, |
408 | | const unsigned char *npub, |
409 | | const unsigned char *k) const = 0; |
410 | | public: |
411 | 85 | std::optional<component::Ciphertext> Encrypt(const operation::SymmetricEncrypt& op) const { |
412 | 85 | std::optional<component::Ciphertext> ret = std::nullopt; |
413 | | |
414 | 85 | uint8_t* out = util::malloc(op.ciphertextSize); |
415 | | |
416 | | /* Operation must support tag output */ |
417 | 85 | CF_CHECK_NE(op.tagSize, std::nullopt); |
418 | 52 | CF_CHECK_GTE(op.tagSize, TAGLEN); |
419 | | |
420 | | /* Output must be able to hold message + tag */ |
421 | 38 | CF_CHECK_GTE(op.ciphertextSize, op.cleartext.GetSize() + TAGLEN); |
422 | | |
423 | 19 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); |
424 | 7 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); |
425 | | |
426 | 6 | unsigned long long ciphertext_len; |
427 | | |
428 | 6 | CF_CHECK_EQ(encrypt( |
429 | 6 | out, |
430 | 6 | &ciphertext_len, |
431 | 6 | op.cleartext.GetPtr(), |
432 | 6 | op.cleartext.GetSize(), |
433 | 6 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), |
434 | 6 | op.aad == std::nullopt ? 0: op.aad->GetSize(), |
435 | 6 | nullptr, |
436 | 6 | op.cipher.iv.GetPtr(), |
437 | 6 | op.cipher.key.GetPtr()), 0); |
438 | | |
439 | 6 | if ( ciphertext_len > op.cleartext.GetSize() + TAGLEN ) { |
440 | 0 | abort(); |
441 | 0 | } |
442 | 6 | if ( ciphertext_len < TAGLEN ) { |
443 | 0 | abort(); |
444 | 0 | } |
445 | | |
446 | 6 | ret = component::Ciphertext( |
447 | 6 | Buffer(out, ciphertext_len - TAGLEN), |
448 | 6 | Buffer(out + ciphertext_len - TAGLEN, TAGLEN)); |
449 | 85 | end: |
450 | 85 | util::free(out); |
451 | 85 | return ret; |
452 | 6 | } cryptofuzz::module::libsodium_detail::AEAD<16ul, 12ul, 32ul>::Encrypt(cryptofuzz::operation::SymmetricEncrypt const&) const Line | Count | Source | 411 | 54 | std::optional<component::Ciphertext> Encrypt(const operation::SymmetricEncrypt& op) const { | 412 | 54 | std::optional<component::Ciphertext> ret = std::nullopt; | 413 | | | 414 | 54 | uint8_t* out = util::malloc(op.ciphertextSize); | 415 | | | 416 | | /* Operation must support tag output */ | 417 | 54 | CF_CHECK_NE(op.tagSize, std::nullopt); | 418 | 36 | CF_CHECK_GTE(op.tagSize, TAGLEN); | 419 | | | 420 | | /* Output must be able to hold message + tag */ | 421 | 25 | CF_CHECK_GTE(op.ciphertextSize, op.cleartext.GetSize() + TAGLEN); | 422 | | | 423 | 18 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); | 424 | 7 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); | 425 | | | 426 | 6 | unsigned long long ciphertext_len; | 427 | | | 428 | 6 | CF_CHECK_EQ(encrypt( | 429 | 6 | out, | 430 | 6 | &ciphertext_len, | 431 | 6 | op.cleartext.GetPtr(), | 432 | 6 | op.cleartext.GetSize(), | 433 | 6 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), | 434 | 6 | op.aad == std::nullopt ? 0: op.aad->GetSize(), | 435 | 6 | nullptr, | 436 | 6 | op.cipher.iv.GetPtr(), | 437 | 6 | op.cipher.key.GetPtr()), 0); | 438 | | | 439 | 6 | if ( ciphertext_len > op.cleartext.GetSize() + TAGLEN ) { | 440 | 0 | abort(); | 441 | 0 | } | 442 | 6 | if ( ciphertext_len < TAGLEN ) { | 443 | 0 | abort(); | 444 | 0 | } | 445 | | | 446 | 6 | ret = component::Ciphertext( | 447 | 6 | Buffer(out, ciphertext_len - TAGLEN), | 448 | 6 | Buffer(out + ciphertext_len - TAGLEN, TAGLEN)); | 449 | 54 | end: | 450 | 54 | util::free(out); | 451 | 54 | return ret; | 452 | 6 | } |
cryptofuzz::module::libsodium_detail::AEAD<16ul, 8ul, 32ul>::Encrypt(cryptofuzz::operation::SymmetricEncrypt const&) const Line | Count | Source | 411 | 10 | std::optional<component::Ciphertext> Encrypt(const operation::SymmetricEncrypt& op) const { | 412 | 10 | std::optional<component::Ciphertext> ret = std::nullopt; | 413 | | | 414 | 10 | uint8_t* out = util::malloc(op.ciphertextSize); | 415 | | | 416 | | /* Operation must support tag output */ | 417 | 10 | CF_CHECK_NE(op.tagSize, std::nullopt); | 418 | 5 | CF_CHECK_GTE(op.tagSize, TAGLEN); | 419 | | | 420 | | /* Output must be able to hold message + tag */ | 421 | 4 | CF_CHECK_GTE(op.ciphertextSize, op.cleartext.GetSize() + TAGLEN); | 422 | |
| 423 | 0 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); | 424 | 0 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); | 425 | |
| 426 | 0 | unsigned long long ciphertext_len; | 427 | |
| 428 | 0 | CF_CHECK_EQ(encrypt( | 429 | 0 | out, | 430 | 0 | &ciphertext_len, | 431 | 0 | op.cleartext.GetPtr(), | 432 | 0 | op.cleartext.GetSize(), | 433 | 0 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), | 434 | 0 | op.aad == std::nullopt ? 0: op.aad->GetSize(), | 435 | 0 | nullptr, | 436 | 0 | op.cipher.iv.GetPtr(), | 437 | 0 | op.cipher.key.GetPtr()), 0); | 438 | |
| 439 | 0 | if ( ciphertext_len > op.cleartext.GetSize() + TAGLEN ) { | 440 | 0 | abort(); | 441 | 0 | } | 442 | 0 | if ( ciphertext_len < TAGLEN ) { | 443 | 0 | abort(); | 444 | 0 | } | 445 | | | 446 | 0 | ret = component::Ciphertext( | 447 | 0 | Buffer(out, ciphertext_len - TAGLEN), | 448 | 0 | Buffer(out + ciphertext_len - TAGLEN, TAGLEN)); | 449 | 10 | end: | 450 | 10 | util::free(out); | 451 | 10 | return ret; | 452 | 0 | } |
cryptofuzz::module::libsodium_detail::AEAD<16ul, 24ul, 32ul>::Encrypt(cryptofuzz::operation::SymmetricEncrypt const&) const Line | Count | Source | 411 | 21 | std::optional<component::Ciphertext> Encrypt(const operation::SymmetricEncrypt& op) const { | 412 | 21 | std::optional<component::Ciphertext> ret = std::nullopt; | 413 | | | 414 | 21 | uint8_t* out = util::malloc(op.ciphertextSize); | 415 | | | 416 | | /* Operation must support tag output */ | 417 | 21 | CF_CHECK_NE(op.tagSize, std::nullopt); | 418 | 11 | CF_CHECK_GTE(op.tagSize, TAGLEN); | 419 | | | 420 | | /* Output must be able to hold message + tag */ | 421 | 9 | CF_CHECK_GTE(op.ciphertextSize, op.cleartext.GetSize() + TAGLEN); | 422 | | | 423 | 1 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); | 424 | 0 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); | 425 | |
| 426 | 0 | unsigned long long ciphertext_len; | 427 | |
| 428 | 0 | CF_CHECK_EQ(encrypt( | 429 | 0 | out, | 430 | 0 | &ciphertext_len, | 431 | 0 | op.cleartext.GetPtr(), | 432 | 0 | op.cleartext.GetSize(), | 433 | 0 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), | 434 | 0 | op.aad == std::nullopt ? 0: op.aad->GetSize(), | 435 | 0 | nullptr, | 436 | 0 | op.cipher.iv.GetPtr(), | 437 | 0 | op.cipher.key.GetPtr()), 0); | 438 | |
| 439 | 0 | if ( ciphertext_len > op.cleartext.GetSize() + TAGLEN ) { | 440 | 0 | abort(); | 441 | 0 | } | 442 | 0 | if ( ciphertext_len < TAGLEN ) { | 443 | 0 | abort(); | 444 | 0 | } | 445 | | | 446 | 0 | ret = component::Ciphertext( | 447 | 0 | Buffer(out, ciphertext_len - TAGLEN), | 448 | 0 | Buffer(out + ciphertext_len - TAGLEN, TAGLEN)); | 449 | 21 | end: | 450 | 21 | util::free(out); | 451 | 21 | return ret; | 452 | 0 | } |
|
453 | | |
454 | 71 | std::optional<component::Cleartext> Decrypt(const operation::SymmetricDecrypt& op) const { |
455 | 71 | std::optional<component::Cleartext> ret = std::nullopt; |
456 | | |
457 | 71 | size_t ciphertextAndTagSize; |
458 | 71 | uint8_t* ciphertextAndTag = nullptr; |
459 | 71 | uint8_t* out = nullptr; |
460 | | |
461 | 71 | CF_CHECK_GTE(op.cleartextSize, op.ciphertext.GetSize()); |
462 | | |
463 | 45 | CF_CHECK_NE(op.tag, std::nullopt); |
464 | | |
465 | | /* Concatenate ciphertext + tag */ |
466 | 31 | { |
467 | 31 | ciphertextAndTagSize = op.ciphertext.GetSize() + op.tag->GetSize(); |
468 | 31 | ciphertextAndTag = util::malloc(ciphertextAndTagSize); |
469 | | |
470 | 31 | if ( op.ciphertext.GetSize() ) { |
471 | 27 | memcpy(ciphertextAndTag, op.ciphertext.GetPtr(), op.ciphertext.GetSize()); |
472 | 27 | } |
473 | 31 | if ( op.tag->GetSize() ) { |
474 | 30 | memcpy(ciphertextAndTag + op.ciphertext.GetSize(), op.tag->GetPtr(), op.tag->GetSize()); |
475 | 30 | } |
476 | 31 | } |
477 | | |
478 | 31 | CF_CHECK_EQ(op.tag->GetSize(), TAGLEN); |
479 | 11 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); |
480 | 10 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); |
481 | | |
482 | 10 | out = util::malloc(op.cleartextSize); |
483 | | |
484 | 10 | unsigned long long cleartext_len; |
485 | | |
486 | 10 | CF_CHECK_EQ(decrypt( |
487 | 10 | out, |
488 | 10 | &cleartext_len, |
489 | 10 | nullptr, |
490 | 10 | ciphertextAndTag, |
491 | 10 | ciphertextAndTagSize, |
492 | 10 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), |
493 | 10 | op.aad == std::nullopt ? 0: op.aad->GetSize(), |
494 | 10 | op.cipher.iv.GetPtr(), |
495 | 10 | op.cipher.key.GetPtr()), 0); |
496 | | |
497 | 1 | ret = component::Cleartext(out, cleartext_len); |
498 | | |
499 | 71 | end: |
500 | 71 | util::free(ciphertextAndTag); |
501 | 71 | util::free(out); |
502 | | |
503 | 71 | return ret; |
504 | 1 | } cryptofuzz::module::libsodium_detail::AEAD<16ul, 12ul, 32ul>::Decrypt(cryptofuzz::operation::SymmetricDecrypt const&) const Line | Count | Source | 454 | 48 | std::optional<component::Cleartext> Decrypt(const operation::SymmetricDecrypt& op) const { | 455 | 48 | std::optional<component::Cleartext> ret = std::nullopt; | 456 | | | 457 | 48 | size_t ciphertextAndTagSize; | 458 | 48 | uint8_t* ciphertextAndTag = nullptr; | 459 | 48 | uint8_t* out = nullptr; | 460 | | | 461 | 48 | CF_CHECK_GTE(op.cleartextSize, op.ciphertext.GetSize()); | 462 | | | 463 | 33 | CF_CHECK_NE(op.tag, std::nullopt); | 464 | | | 465 | | /* Concatenate ciphertext + tag */ | 466 | 25 | { | 467 | 25 | ciphertextAndTagSize = op.ciphertext.GetSize() + op.tag->GetSize(); | 468 | 25 | ciphertextAndTag = util::malloc(ciphertextAndTagSize); | 469 | | | 470 | 25 | if ( op.ciphertext.GetSize() ) { | 471 | 21 | memcpy(ciphertextAndTag, op.ciphertext.GetPtr(), op.ciphertext.GetSize()); | 472 | 21 | } | 473 | 25 | if ( op.tag->GetSize() ) { | 474 | 25 | memcpy(ciphertextAndTag + op.ciphertext.GetSize(), op.tag->GetPtr(), op.tag->GetSize()); | 475 | 25 | } | 476 | 25 | } | 477 | | | 478 | 25 | CF_CHECK_EQ(op.tag->GetSize(), TAGLEN); | 479 | 11 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); | 480 | 10 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); | 481 | | | 482 | 10 | out = util::malloc(op.cleartextSize); | 483 | | | 484 | 10 | unsigned long long cleartext_len; | 485 | | | 486 | 10 | CF_CHECK_EQ(decrypt( | 487 | 10 | out, | 488 | 10 | &cleartext_len, | 489 | 10 | nullptr, | 490 | 10 | ciphertextAndTag, | 491 | 10 | ciphertextAndTagSize, | 492 | 10 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), | 493 | 10 | op.aad == std::nullopt ? 0: op.aad->GetSize(), | 494 | 10 | op.cipher.iv.GetPtr(), | 495 | 10 | op.cipher.key.GetPtr()), 0); | 496 | | | 497 | 1 | ret = component::Cleartext(out, cleartext_len); | 498 | | | 499 | 48 | end: | 500 | 48 | util::free(ciphertextAndTag); | 501 | 48 | util::free(out); | 502 | | | 503 | 48 | return ret; | 504 | 1 | } |
cryptofuzz::module::libsodium_detail::AEAD<16ul, 8ul, 32ul>::Decrypt(cryptofuzz::operation::SymmetricDecrypt const&) const Line | Count | Source | 454 | 13 | std::optional<component::Cleartext> Decrypt(const operation::SymmetricDecrypt& op) const { | 455 | 13 | std::optional<component::Cleartext> ret = std::nullopt; | 456 | | | 457 | 13 | size_t ciphertextAndTagSize; | 458 | 13 | uint8_t* ciphertextAndTag = nullptr; | 459 | 13 | uint8_t* out = nullptr; | 460 | | | 461 | 13 | CF_CHECK_GTE(op.cleartextSize, op.ciphertext.GetSize()); | 462 | | | 463 | 6 | CF_CHECK_NE(op.tag, std::nullopt); | 464 | | | 465 | | /* Concatenate ciphertext + tag */ | 466 | 2 | { | 467 | 2 | ciphertextAndTagSize = op.ciphertext.GetSize() + op.tag->GetSize(); | 468 | 2 | ciphertextAndTag = util::malloc(ciphertextAndTagSize); | 469 | | | 470 | 2 | if ( op.ciphertext.GetSize() ) { | 471 | 2 | memcpy(ciphertextAndTag, op.ciphertext.GetPtr(), op.ciphertext.GetSize()); | 472 | 2 | } | 473 | 2 | if ( op.tag->GetSize() ) { | 474 | 2 | memcpy(ciphertextAndTag + op.ciphertext.GetSize(), op.tag->GetPtr(), op.tag->GetSize()); | 475 | 2 | } | 476 | 2 | } | 477 | | | 478 | 2 | CF_CHECK_EQ(op.tag->GetSize(), TAGLEN); | 479 | 0 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); | 480 | 0 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); | 481 | |
| 482 | 0 | out = util::malloc(op.cleartextSize); | 483 | |
| 484 | 0 | unsigned long long cleartext_len; | 485 | |
| 486 | 0 | CF_CHECK_EQ(decrypt( | 487 | 0 | out, | 488 | 0 | &cleartext_len, | 489 | 0 | nullptr, | 490 | 0 | ciphertextAndTag, | 491 | 0 | ciphertextAndTagSize, | 492 | 0 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), | 493 | 0 | op.aad == std::nullopt ? 0: op.aad->GetSize(), | 494 | 0 | op.cipher.iv.GetPtr(), | 495 | 0 | op.cipher.key.GetPtr()), 0); | 496 | |
| 497 | 0 | ret = component::Cleartext(out, cleartext_len); | 498 | |
| 499 | 13 | end: | 500 | 13 | util::free(ciphertextAndTag); | 501 | 13 | util::free(out); | 502 | | | 503 | 13 | return ret; | 504 | 0 | } |
cryptofuzz::module::libsodium_detail::AEAD<16ul, 24ul, 32ul>::Decrypt(cryptofuzz::operation::SymmetricDecrypt const&) const Line | Count | Source | 454 | 10 | std::optional<component::Cleartext> Decrypt(const operation::SymmetricDecrypt& op) const { | 455 | 10 | std::optional<component::Cleartext> ret = std::nullopt; | 456 | | | 457 | 10 | size_t ciphertextAndTagSize; | 458 | 10 | uint8_t* ciphertextAndTag = nullptr; | 459 | 10 | uint8_t* out = nullptr; | 460 | | | 461 | 10 | CF_CHECK_GTE(op.cleartextSize, op.ciphertext.GetSize()); | 462 | | | 463 | 6 | CF_CHECK_NE(op.tag, std::nullopt); | 464 | | | 465 | | /* Concatenate ciphertext + tag */ | 466 | 4 | { | 467 | 4 | ciphertextAndTagSize = op.ciphertext.GetSize() + op.tag->GetSize(); | 468 | 4 | ciphertextAndTag = util::malloc(ciphertextAndTagSize); | 469 | | | 470 | 4 | if ( op.ciphertext.GetSize() ) { | 471 | 4 | memcpy(ciphertextAndTag, op.ciphertext.GetPtr(), op.ciphertext.GetSize()); | 472 | 4 | } | 473 | 4 | if ( op.tag->GetSize() ) { | 474 | 3 | memcpy(ciphertextAndTag + op.ciphertext.GetSize(), op.tag->GetPtr(), op.tag->GetSize()); | 475 | 3 | } | 476 | 4 | } | 477 | | | 478 | 4 | CF_CHECK_EQ(op.tag->GetSize(), TAGLEN); | 479 | 0 | CF_CHECK_EQ(op.cipher.iv.GetSize(), IVLEN); | 480 | 0 | CF_CHECK_EQ(op.cipher.key.GetSize(), KEYLEN); | 481 | |
| 482 | 0 | out = util::malloc(op.cleartextSize); | 483 | |
| 484 | 0 | unsigned long long cleartext_len; | 485 | |
| 486 | 0 | CF_CHECK_EQ(decrypt( | 487 | 0 | out, | 488 | 0 | &cleartext_len, | 489 | 0 | nullptr, | 490 | 0 | ciphertextAndTag, | 491 | 0 | ciphertextAndTagSize, | 492 | 0 | op.aad == std::nullopt ? (const uint8_t*)0x12 : op.aad->GetPtr(), | 493 | 0 | op.aad == std::nullopt ? 0: op.aad->GetSize(), | 494 | 0 | op.cipher.iv.GetPtr(), | 495 | 0 | op.cipher.key.GetPtr()), 0); | 496 | |
| 497 | 0 | ret = component::Cleartext(out, cleartext_len); | 498 | |
| 499 | 10 | end: | 500 | 10 | util::free(ciphertextAndTag); | 501 | 10 | util::free(out); | 502 | | | 503 | 10 | return ret; | 504 | 0 | } |
|
505 | | }; |
506 | | |
507 | | static class : public AEAD< |
508 | | crypto_aead_aes256gcm_ABYTES, |
509 | | crypto_aead_aes256gcm_NPUBBYTES, |
510 | | crypto_aead_aes256gcm_KEYBYTES> { |
511 | | private: |
512 | | int encrypt(unsigned char *c, |
513 | | unsigned long long *clen, |
514 | | const unsigned char *m, |
515 | | unsigned long long mlen, |
516 | | const unsigned char *ad, |
517 | | unsigned long long adlen, |
518 | | const unsigned char *nsec, |
519 | | const unsigned char *npub, |
520 | 0 | const unsigned char *k) const override { |
521 | 0 | return crypto_aead_aes256gcm_encrypt(c, clen, m, mlen, ad, adlen, nsec, npub, k); |
522 | 0 | } |
523 | | |
524 | | int decrypt(unsigned char *m, |
525 | | unsigned long long *mlen, |
526 | | unsigned char *nsec, |
527 | | const unsigned char *c, |
528 | | unsigned long long clen, |
529 | | const unsigned char *ad, |
530 | | unsigned long long adlen, |
531 | | const unsigned char *npub, |
532 | 0 | const unsigned char *k) const override { |
533 | 0 | return crypto_aead_aes256gcm_decrypt(m, mlen, nsec, c, clen, ad, adlen, npub, k); |
534 | 0 | } |
535 | | } aes_256_gcm; |
536 | | |
537 | | static class : public AEAD< |
538 | | crypto_aead_aes256gcm_ABYTES, |
539 | | crypto_aead_aes256gcm_NPUBBYTES, |
540 | | crypto_aead_aes256gcm_KEYBYTES> { |
541 | | private: |
542 | | int encrypt(unsigned char *c, |
543 | | unsigned long long *clen, |
544 | | const unsigned char *m, |
545 | | unsigned long long mlen, |
546 | | const unsigned char *ad, |
547 | | unsigned long long adlen, |
548 | | const unsigned char *nsec, |
549 | | const unsigned char *npub, |
550 | 0 | const unsigned char *k) const override { |
551 | 0 | int ret = -1; |
552 | |
|
553 | 0 | crypto_aead_aes256gcm_state ctx; |
554 | 0 | CF_CHECK_EQ(crypto_aead_aes256gcm_beforenm(&ctx, k), 0); |
555 | |
|
556 | 0 | CF_CHECK_EQ(crypto_aead_aes256gcm_encrypt_afternm(c, clen, m, mlen, ad, adlen, nsec, npub, &ctx), 0); |
557 | |
|
558 | 0 | ret = 0; |
559 | |
|
560 | 0 | end: |
561 | 0 | return ret; |
562 | 0 | } |
563 | | |
564 | | int decrypt(unsigned char *m, |
565 | | unsigned long long *mlen, |
566 | | unsigned char *nsec, |
567 | | const unsigned char *c, |
568 | | unsigned long long clen, |
569 | | const unsigned char *ad, |
570 | | unsigned long long adlen, |
571 | | const unsigned char *npub, |
572 | 0 | const unsigned char *k) const override { |
573 | 0 | int ret = -1; |
574 | 0 | crypto_aead_aes256gcm_state ctx; |
575 | 0 | CF_CHECK_EQ(crypto_aead_aes256gcm_beforenm(&ctx, k), 0); |
576 | |
|
577 | 0 | CF_CHECK_EQ(crypto_aead_aes256gcm_decrypt_afternm(m, mlen, nsec, c, clen, ad, adlen, npub, &ctx), 0); |
578 | |
|
579 | 0 | ret = 0; |
580 | 0 | end: |
581 | 0 | return ret; |
582 | 0 | } |
583 | | } aes_256_gcm_precompute; |
584 | | |
585 | | static class : public AEAD< |
586 | | crypto_aead_chacha20poly1305_ABYTES, |
587 | | crypto_aead_chacha20poly1305_NPUBBYTES, |
588 | | crypto_aead_chacha20poly1305_KEYBYTES> { |
589 | | private: |
590 | | int encrypt(unsigned char *c, |
591 | | unsigned long long *clen, |
592 | | const unsigned char *m, |
593 | | unsigned long long mlen, |
594 | | const unsigned char *ad, |
595 | | unsigned long long adlen, |
596 | | const unsigned char *nsec, |
597 | | const unsigned char *npub, |
598 | 0 | const unsigned char *k) const override { |
599 | 0 | return crypto_aead_chacha20poly1305_encrypt(c, clen, m, mlen, ad, adlen, nsec, npub, k); |
600 | 0 | } |
601 | | |
602 | | int decrypt(unsigned char *m, |
603 | | unsigned long long *mlen, |
604 | | unsigned char *nsec, |
605 | | const unsigned char *c, |
606 | | unsigned long long clen, |
607 | | const unsigned char *ad, |
608 | | unsigned long long adlen, |
609 | | const unsigned char *npub, |
610 | 0 | const unsigned char *k) const override { |
611 | 0 | return crypto_aead_chacha20poly1305_decrypt(m, mlen, nsec, c, clen, ad, adlen, npub, k); |
612 | 0 | } |
613 | | } chacha20_poly1305_libsodium; |
614 | | |
615 | | static class : public AEAD< |
616 | | crypto_aead_chacha20poly1305_IETF_ABYTES, |
617 | | crypto_aead_chacha20poly1305_IETF_NPUBBYTES, |
618 | | crypto_aead_chacha20poly1305_IETF_KEYBYTES> { |
619 | | private: |
620 | | int encrypt(unsigned char *c, |
621 | | unsigned long long *clen, |
622 | | const unsigned char *m, |
623 | | unsigned long long mlen, |
624 | | const unsigned char *ad, |
625 | | unsigned long long adlen, |
626 | | const unsigned char *nsec, |
627 | | const unsigned char *npub, |
628 | 6 | const unsigned char *k) const override { |
629 | 6 | return crypto_aead_chacha20poly1305_ietf_encrypt(c, clen, m, mlen, ad, adlen, nsec, npub, k); |
630 | 6 | } |
631 | | |
632 | | int decrypt(unsigned char *m, |
633 | | unsigned long long *mlen, |
634 | | unsigned char *nsec, |
635 | | const unsigned char *c, |
636 | | unsigned long long clen, |
637 | | const unsigned char *ad, |
638 | | unsigned long long adlen, |
639 | | const unsigned char *npub, |
640 | 10 | const unsigned char *k) const override { |
641 | 10 | return crypto_aead_chacha20poly1305_ietf_decrypt(m, mlen, nsec, c, clen, ad, adlen, npub, k); |
642 | 10 | } |
643 | | } chacha20_poly1305; |
644 | | |
645 | | static class : public AEAD< |
646 | | crypto_aead_xchacha20poly1305_IETF_ABYTES, |
647 | | crypto_aead_xchacha20poly1305_IETF_NPUBBYTES, |
648 | | crypto_aead_xchacha20poly1305_IETF_KEYBYTES> { |
649 | | private: |
650 | | int encrypt(unsigned char *c, |
651 | | unsigned long long *clen, |
652 | | const unsigned char *m, |
653 | | unsigned long long mlen, |
654 | | const unsigned char *ad, |
655 | | unsigned long long adlen, |
656 | | const unsigned char *nsec, |
657 | | const unsigned char *npub, |
658 | 0 | const unsigned char *k) const override { |
659 | 0 | return crypto_aead_xchacha20poly1305_ietf_encrypt(c, clen, m, mlen, ad, adlen, nsec, npub, k); |
660 | 0 | } |
661 | | |
662 | | int decrypt(unsigned char *m, |
663 | | unsigned long long *mlen, |
664 | | unsigned char *nsec, |
665 | | const unsigned char *c, |
666 | | unsigned long long clen, |
667 | | const unsigned char *ad, |
668 | | unsigned long long adlen, |
669 | | const unsigned char *npub, |
670 | 0 | const unsigned char *k) const override { |
671 | 0 | return crypto_aead_xchacha20poly1305_ietf_decrypt(m, mlen, nsec, c, clen, ad, adlen, npub, k); |
672 | 0 | } |
673 | | } xchacha20_poly1305; |
674 | | |
675 | | } /* namespace libsodium_detail */ |
676 | | |
677 | 1.47k | std::optional<component::Ciphertext> libsodium::OpSymmetricEncrypt(operation::SymmetricEncrypt& op) { |
678 | 1.47k | uint8_t* out = nullptr; |
679 | | |
680 | 1.47k | switch ( op.cipher.cipherType.Get() ) { |
681 | 27 | case CF_CIPHER("AES_256_GCM"): |
682 | 27 | { |
683 | 27 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
684 | 27 | bool usePrecomputation = false; |
685 | 27 | try { |
686 | 27 | usePrecomputation = ds.Get<bool>(); |
687 | 27 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
688 | 17 | } |
689 | | |
690 | 27 | if ( usePrecomputation == false ) { |
691 | 22 | return libsodium_detail::aes_256_gcm.Encrypt(op); |
692 | 22 | } else { |
693 | 5 | return libsodium_detail::aes_256_gcm_precompute.Encrypt(op); |
694 | 5 | } |
695 | 27 | } |
696 | 0 | break; |
697 | 10 | case CF_CIPHER("CHACHA20_POLY1305_LIBSODIUM"): |
698 | 10 | { |
699 | 10 | return libsodium_detail::chacha20_poly1305_libsodium.Encrypt(op); |
700 | 27 | } |
701 | 0 | break; |
702 | 27 | case CF_CIPHER("CHACHA20_POLY1305"): |
703 | 27 | { |
704 | 27 | return libsodium_detail::chacha20_poly1305.Encrypt(op); |
705 | 27 | } |
706 | 0 | break; |
707 | 21 | case CF_CIPHER("XCHACHA20_POLY1305"): |
708 | 21 | { |
709 | 21 | return libsodium_detail::xchacha20_poly1305.Encrypt(op); |
710 | 27 | } |
711 | 0 | break; |
712 | 26 | case CF_CIPHER("CHACHA20"): |
713 | 26 | { |
714 | 26 | CF_CHECK_GTE(op.ciphertextSize, op.cleartext.GetSize()); |
715 | 14 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_stream_chacha20_ietf_KEYBYTES); |
716 | 9 | CF_CHECK_EQ(op.cipher.iv.GetSize(), crypto_stream_chacha20_ietf_NONCEBYTES); |
717 | 2 | out = util::malloc(op.ciphertextSize); |
718 | 2 | CF_CHECK_EQ(crypto_stream_chacha20_ietf_xor_ic(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.iv.GetPtr(), 0, op.cipher.key.GetPtr()), 0); |
719 | 2 | auto ret = component::Ciphertext(Buffer(out, op.cleartext.GetSize())); |
720 | 2 | util::free(out); |
721 | 2 | return ret; |
722 | 2 | } |
723 | 0 | break; |
724 | 6 | case CF_CIPHER("SALSA20_256"): |
725 | 12 | case CF_CIPHER("SALSA20_12_256"): |
726 | 12 | { |
727 | 12 | CF_CHECK_GTE(op.ciphertextSize, op.cleartext.GetSize()); |
728 | 5 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_stream_salsa20_KEYBYTES); |
729 | 1 | CF_CHECK_EQ(op.cipher.iv.GetSize(), crypto_stream_salsa20_NONCEBYTES); |
730 | 1 | out = util::malloc(op.ciphertextSize); |
731 | 1 | if ( op.cipher.cipherType.Get() == CF_CIPHER("SALSA20_256") ) { |
732 | 0 | CF_CHECK_EQ(crypto_stream_salsa20_xor(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.iv.GetPtr(), op.cipher.key.GetPtr()), 0); |
733 | 1 | } else { |
734 | 1 | CF_CHECK_EQ(crypto_stream_salsa2012_xor(out, op.cleartext.GetPtr(), op.cleartext.GetSize(), op.cipher.iv.GetPtr(), op.cipher.key.GetPtr()), 0); |
735 | 1 | } |
736 | 1 | auto ret = component::Ciphertext(Buffer(out, op.cleartext.GetSize())); |
737 | 1 | util::free(out); |
738 | 1 | return ret; |
739 | 1 | } |
740 | 0 | break; |
741 | 1.35k | default: |
742 | 1.35k | return std::nullopt; |
743 | 1.47k | } |
744 | | |
745 | 35 | end: |
746 | 35 | util::free(out); |
747 | 35 | return std::nullopt; |
748 | 1.47k | } |
749 | | |
750 | 1.42k | std::optional<component::Cleartext> libsodium::OpSymmetricDecrypt(operation::SymmetricDecrypt& op) { |
751 | 1.42k | uint8_t* out = nullptr; |
752 | | |
753 | 1.42k | switch ( op.cipher.cipherType.Get() ) { |
754 | 15 | case CF_CIPHER("AES_256_GCM"): |
755 | 15 | { |
756 | 15 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
757 | 15 | bool usePrecomputation = false; |
758 | 15 | try { |
759 | 15 | usePrecomputation = ds.Get<bool>(); |
760 | 15 | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
761 | 6 | } |
762 | | |
763 | 15 | if ( usePrecomputation == false ) { |
764 | 9 | return libsodium_detail::aes_256_gcm.Decrypt(op); |
765 | 9 | } else { |
766 | 6 | return libsodium_detail::aes_256_gcm_precompute.Decrypt(op); |
767 | 6 | } |
768 | 15 | } |
769 | 0 | break; |
770 | 13 | case CF_CIPHER("CHACHA20_POLY1305_LIBSODIUM"): |
771 | 13 | { |
772 | 13 | return libsodium_detail::chacha20_poly1305_libsodium.Decrypt(op); |
773 | 15 | } |
774 | 0 | break; |
775 | 33 | case CF_CIPHER("CHACHA20_POLY1305"): |
776 | 33 | { |
777 | 33 | return libsodium_detail::chacha20_poly1305.Decrypt(op); |
778 | 15 | } |
779 | 0 | break; |
780 | 10 | case CF_CIPHER("XCHACHA20_POLY1305"): |
781 | 10 | { |
782 | 10 | return libsodium_detail::xchacha20_poly1305.Decrypt(op); |
783 | 15 | } |
784 | 0 | break; |
785 | 15 | case CF_CIPHER("CHACHA20"): |
786 | 15 | { |
787 | 15 | CF_CHECK_GTE(op.cleartextSize, op.ciphertext.GetSize()); |
788 | 6 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_stream_chacha20_ietf_KEYBYTES); |
789 | 2 | CF_CHECK_EQ(op.cipher.iv.GetSize(), crypto_stream_chacha20_ietf_NONCEBYTES); |
790 | 2 | out = util::malloc(op.cleartextSize); |
791 | 2 | CF_CHECK_EQ(crypto_stream_chacha20_ietf_xor_ic(out, op.ciphertext.GetPtr(), op.ciphertext.GetSize(), op.cipher.iv.GetPtr(), 0, op.cipher.key.GetPtr()), 0); |
792 | 2 | auto ret = component::Cleartext(Buffer(out, op.ciphertext.GetSize())); |
793 | 2 | util::free(out); |
794 | 2 | return ret; |
795 | 2 | } |
796 | 0 | break; |
797 | 5 | case CF_CIPHER("SALSA20_256"): |
798 | 12 | case CF_CIPHER("SALSA20_12_256"): |
799 | 12 | { |
800 | 12 | CF_CHECK_GTE(op.cleartextSize, op.ciphertext.GetSize()); |
801 | 8 | CF_CHECK_EQ(op.cipher.key.GetSize(), crypto_stream_salsa20_KEYBYTES); |
802 | 2 | CF_CHECK_EQ(op.cipher.iv.GetSize(), crypto_stream_salsa20_NONCEBYTES); |
803 | 1 | out = util::malloc(op.cleartextSize); |
804 | 1 | if ( op.cipher.cipherType.Get() == CF_CIPHER("SALSA20_256") ) { |
805 | 0 | CF_CHECK_EQ(crypto_stream_salsa20_xor(out, op.ciphertext.GetPtr(), op.ciphertext.GetSize(), op.cipher.iv.GetPtr(), op.cipher.key.GetPtr()), 0); |
806 | 1 | } else { |
807 | 1 | CF_CHECK_EQ(crypto_stream_salsa2012_xor(out, op.ciphertext.GetPtr(), op.ciphertext.GetSize(), op.cipher.iv.GetPtr(), op.cipher.key.GetPtr()), 0); |
808 | 1 | } |
809 | 1 | auto ret = component::Cleartext(Buffer(out, op.ciphertext.GetSize())); |
810 | 1 | util::free(out); |
811 | 1 | return ret; |
812 | 1 | } |
813 | 0 | break; |
814 | 1.32k | default: |
815 | 1.32k | return std::nullopt; |
816 | 1.42k | } |
817 | | |
818 | 24 | end: |
819 | 24 | util::free(out); |
820 | 24 | return std::nullopt; |
821 | 1.42k | } |
822 | | |
823 | 526 | std::optional<component::Key> libsodium::OpKDF_ARGON2(operation::KDF_ARGON2& op) { |
824 | 526 | std::optional<component::Key> ret = std::nullopt; |
825 | 526 | uint8_t* out = util::malloc(op.keySize); |
826 | | |
827 | 526 | CF_CHECK_EQ(op.salt.GetSize(), crypto_pwhash_SALTBYTES); |
828 | 11 | CF_CHECK_EQ(op.threads, 1); |
829 | 6 | CF_CHECK_GTE(op.keySize, crypto_pwhash_BYTES_MIN); |
830 | 6 | CF_CHECK_GTE(op.password.GetSize(), crypto_pwhash_PASSWD_MIN); |
831 | 6 | CF_CHECK_LTE(op.password.GetSize(), crypto_pwhash_PASSWD_MAX); |
832 | 6 | CF_CHECK_GTE(op.iterations, crypto_pwhash_OPSLIMIT_MIN); |
833 | 5 | CF_CHECK_LTE(op.iterations, crypto_pwhash_OPSLIMIT_MAX); |
834 | 5 | CF_CHECK_GTE(op.memory * 1024, crypto_pwhash_MEMLIMIT_MIN); |
835 | | //CF_CHECK_LTE(op.memory, crypto_pwhash_MEMLIMIT_MAX); |
836 | | |
837 | 5 | CF_CHECK_EQ(op.type == 1 || op.type == 2, true); |
838 | 4 | CF_CHECK_EQ(crypto_pwhash( |
839 | 4 | out, |
840 | 4 | op.keySize, |
841 | 4 | (const char*)op.password.GetPtr(), |
842 | 4 | op.password.GetSize(), |
843 | 4 | op.salt.GetPtr(), |
844 | 4 | op.iterations, |
845 | 4 | op.memory * 1024, |
846 | 4 | op.type == 1 ? crypto_pwhash_ALG_ARGON2I13 : crypto_pwhash_ALG_ARGON2ID13 |
847 | 4 | ), 0); |
848 | | |
849 | 2 | ret = component::Key(out, op.keySize); |
850 | | |
851 | 526 | end: |
852 | 526 | util::free(out); |
853 | | |
854 | 526 | return ret; |
855 | 2 | } |
856 | | |
857 | 508 | std::optional<component::Key> libsodium::OpKDF_SCRYPT(operation::KDF_SCRYPT& op) { |
858 | 508 | std::optional<component::Key> ret = std::nullopt; |
859 | | |
860 | 508 | const size_t outSize = op.keySize; |
861 | 508 | uint8_t* out = util::malloc(outSize); |
862 | | |
863 | 508 | CF_CHECK_EQ(crypto_pwhash_scryptsalsa208sha256_ll( |
864 | 508 | op.password.GetPtr(), |
865 | 508 | op.password.GetSize(), |
866 | 508 | op.salt.GetPtr(), |
867 | 508 | op.salt.GetSize(), |
868 | 508 | op.N, |
869 | 508 | op.r, |
870 | 508 | op.p, |
871 | 508 | out, |
872 | 508 | outSize), 0); |
873 | | |
874 | 332 | ret = component::Key(out, outSize); |
875 | | |
876 | 508 | end: |
877 | 508 | util::free(out); |
878 | | |
879 | 508 | return ret; |
880 | 332 | } |
881 | | |
882 | | } /* namespace module */ |
883 | | } /* namespace cryptofuzz */ |