44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7- #include < libp2p/common/final_action.hpp >
7+ #include < openssl/aead.h >
88#include < libp2p/crypto/chachapoly/chachapoly_impl.hpp>
9- #include < libp2p/crypto/common_functions.hpp>
109#include < libp2p/crypto/error.hpp>
1110
12- using libp2p::common::FinalAction;
13-
1411namespace libp2p ::crypto::chachapoly {
12+ constexpr size_t kTagSize = 16 ;
1513
1614#define IF1 (expr, err, result ) \
1715 if (1 != (expr)) { \
@@ -21,125 +19,75 @@ namespace libp2p::crypto::chachapoly {
2119
2220 ChaCha20Poly1305Impl::ChaCha20Poly1305Impl (Key key)
2321 : key_{key},
24- cipher_{EVP_chacha20_poly1305 ()},
25- block_size_{EVP_CIPHER_block_size (cipher_)} {}
22+ aead_{EVP_aead_chacha20_poly1305 ()},
23+ overhead_{EVP_AEAD_max_overhead (aead_)} {}
24+
25+ outcome::result<void > ChaCha20Poly1305Impl::init (EVP_AEAD_CTX *ctx,
26+ bool encrypt) {
27+ IF1 (EVP_AEAD_CTX_init_with_direction (
28+ ctx,
29+ aead_,
30+ key_.data (),
31+ key_.size (),
32+ kTagSize ,
33+ encrypt ? evp_aead_seal : evp_aead_open),
34+ " EVP_AEAD_CTX_init" ,
35+ OpenSslError::FAILED_INITIALIZE_CONTEXT);
36+ return outcome::success ();
37+ }
2638
2739 outcome::result<Bytes> ChaCha20Poly1305Impl::encrypt (const Nonce &nonce,
2840 BytesIn plaintext,
2941 BytesIn aad) {
30- const auto init_failure = OpenSslError::FAILED_INITIALIZE_OPERATION;
31- std::vector<uint8_t > result;
42+ bssl::ScopedEVP_AEAD_CTX ctx;
43+ OUTCOME_TRY (init (ctx.get (), true ));
44+ Bytes result;
3245 // just reserving the space, possibly without actual memory allocation:
3346 // ciphertext length equals to plaintext length
3447 // one block size for EncryptFinal_ex (usually not required)
3548 // 16 bytes for the tag
36- result.reserve (plaintext.size () + block_size_ + 16 );
37- auto *ctx = EVP_CIPHER_CTX_new ();
38- if (nullptr == ctx) {
39- return OpenSslError::FAILED_INITIALIZE_CONTEXT;
40- }
41- FinalAction free_ctx ([ctx] { EVP_CIPHER_CTX_free (ctx); });
42-
43- IF1 (EVP_EncryptInit_ex (ctx, cipher_, nullptr , nullptr , nullptr ),
44- " Failed to initialize EVP encryption." ,
45- init_failure)
46-
47- IF1 (EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_SET_IVLEN, 12 , nullptr ),
48- " Cannot set AEAD initialization vector length." ,
49- init_failure)
50-
51- IF1 (EVP_EncryptInit_ex (ctx, nullptr , nullptr , key_.data (), nonce.data ()),
52- " Cannot finalize init of encryption engine." ,
53- init_failure)
54-
55- int len{0 };
56- IF1 (EVP_EncryptUpdate (ctx, nullptr , &len, nullptr , plaintext.size ()),
57- " Failed to calculate cipher text length." ,
58- OpenSslError::FAILED_ENCRYPT_UPDATE)
59-
60- // does actual memory allocation
61- result.resize (len + block_size_ + 16 , 0u );
62- if (not aad.empty ()) {
63- IF1 (EVP_EncryptUpdate (ctx, nullptr , &len, aad.data (), aad.size ()),
64- " Failed to apply additional authentication data during encryption." ,
65- OpenSslError::FAILED_ENCRYPT_UPDATE)
66- }
67-
68- IF1 (EVP_EncryptUpdate (
69- ctx, result.data (), &len, plaintext.data (), plaintext.size ()),
70- " Plaintext encryption failed." ,
71- OpenSslError::FAILED_ENCRYPT_UPDATE)
72- int ciphertext_len = len; // without tag size
73- IF1 (EVP_EncryptFinal_ex (ctx, result.data () + len, &len), // NOLINT
74- " Unable to finalize encryption." ,
75- OpenSslError::FAILED_ENCRYPT_FINALIZE)
76-
77- ciphertext_len += len;
78- IF1 (EVP_CIPHER_CTX_ctrl (ctx,
79- EVP_CTRL_AEAD_GET_TAG,
80- EVP_CTRL_AEAD_GET_TAG,
81- result.data () + ciphertext_len), // NOLINT
82- " Failed to write tag." ,
83- OpenSslError::FAILED_ENCRYPT_FINALIZE)
84-
85- // remove the last block_size bytes if those were not used
86- result.resize (ciphertext_len + 16 );
49+ result.resize (plaintext.size () + overhead_);
50+ size_t out_size = 0 ;
51+ IF1 (EVP_AEAD_CTX_seal (ctx.get (),
52+ result.data (),
53+ &out_size,
54+ result.size (),
55+ nonce.data (),
56+ nonce.size (),
57+ plaintext.data (),
58+ plaintext.size (),
59+ aad.data (),
60+ aad.size ()),
61+ " EVP_AEAD_CTX_seal" ,
62+ OpenSslError::FAILED_ENCRYPT_UPDATE);
63+ result.resize (out_size);
8764 return result;
8865 }
8966
9067 outcome::result<Bytes> ChaCha20Poly1305Impl::decrypt (const Nonce &nonce,
9168 BytesIn ciphertext,
9269 BytesIn aad) {
70+ bssl::ScopedEVP_AEAD_CTX ctx;
71+ OUTCOME_TRY (init (ctx.get (), false ));
9372 Bytes result;
9473 // plain text should take less bytes than cipher text,
9574 // at least it would not contain tag-length bytes (16).
9675 // single block size for the case when len(in) == len(out)
97- result.resize (ciphertext.size () + block_size_, 0u );
98- auto *ctx = EVP_CIPHER_CTX_new ();
99- FinalAction free_ctx ([ctx] { EVP_CIPHER_CTX_free (ctx); });
100-
101- IF1 (EVP_DecryptInit_ex (ctx, cipher_, nullptr , nullptr , nullptr ),
102- " Failed to initialize decryption engine." ,
103- OpenSslError::FAILED_INITIALIZE_OPERATION)
104-
105- IF1 (EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_SET_IVLEN, 12 , nullptr ),
106- " Cannot set AEAD initialization vector length." ,
107- OpenSslError::FAILED_INITIALIZE_OPERATION)
108-
109- IF1 (EVP_CIPHER_CTX_ctrl (
110- ctx,
111- EVP_CTRL_AEAD_SET_TAG,
112- EVP_CTRL_AEAD_GET_TAG,
113- (uint8_t *)ciphertext.data () + ciphertext.size () - 16 ), // NOLINT
114- " Failed to specify buffer for further tag reading." ,
115- OpenSslError::FAILED_DECRYPT_UPDATE)
116-
117- IF1 (EVP_DecryptInit_ex (ctx, nullptr , nullptr , key_.data (), nonce.data ()),
118- " Cannot finalize init of decryption engine." ,
119- OpenSslError::FAILED_INITIALIZE_OPERATION)
120-
121- int len{0 };
122- if (not aad.empty ()) {
123- IF1 (EVP_DecryptUpdate (ctx, nullptr , &len, aad.data (), aad.size ()),
124- " Failed to apply additional authentication data during decryption." ,
125- OpenSslError::FAILED_DECRYPT_UPDATE)
126- }
127-
128- IF1 (EVP_DecryptUpdate (ctx,
76+ result.resize (ciphertext.size ());
77+ size_t out_size = 0 ;
78+ IF1 (EVP_AEAD_CTX_open (ctx.get (),
12979 result.data (),
130- &len,
80+ &out_size,
81+ result.size (),
82+ nonce.data (),
83+ nonce.size (),
13184 ciphertext.data (),
132- ciphertext.size () - 16 ),
133- " Ciphertext decryption failed." ,
134- OpenSslError::FAILED_DECRYPT_UPDATE)
135-
136- IF1 (EVP_DecryptFinal_ex (ctx,
137- result.data () + len, // NOLINT
138- &len),
139- " Failed to finalize decryption." ,
140- OpenSslError::FAILED_DECRYPT_FINALIZE);
141-
142- result.resize (ciphertext.size () - 16 );
85+ ciphertext.size (),
86+ aad.data (),
87+ aad.size ()),
88+ " EVP_AEAD_CTX_open" ,
89+ OpenSslError::FAILED_DECRYPT_UPDATE);
90+ result.resize (out_size);
14391 return result;
14492 }
14593
0 commit comments