@@ -258,24 +258,60 @@ HybridCipher::final() {
258258 throw std::runtime_error (" Cipher not initialized. Did you call setArgs()?" );
259259 }
260260
261- int finalLen = 0 ;
262- uint8_t * tempBuf = new uint8_t [EVP_MAX_BLOCK_LENGTH] ;
261+ int mode = getMode () ;
262+ int buf_len = EVP_CIPHER_CTX_block_size (ctx) ;
263263
264- // Finalize the encryption/decryption
265- if (EVP_CipherFinal_ex (
264+ if (!is_cipher && isSupportedAuthenticatedMode (ctx)) {
265+ maybePassAuthTagToOpenSSL ();
266+ }
267+
268+ bool ok;
269+ int out_len = 0 ;
270+ uint8_t * out = new uint8_t [buf_len];
271+
272+ // In CCM mode, final() only checks whether authentication failed in
273+ // update(). EVP_CipherFinal_ex must not be called and will fail.
274+ if (!is_cipher && mode == EVP_CIPH_CCM_MODE) {
275+ ok = !pending_auth_failed;
276+ out = new uint8_t [0 ];
277+ } else {
278+ ok = EVP_CipherFinal_ex (
279+ ctx,
280+ out,
281+ &out_len
282+ ) == 1 ;
283+
284+ // Additional operations for authenticated modes
285+ if (ok && is_cipher && isAuthenticatedMode ()) {
286+ // In GCM mode: default to 16 bytes.
287+ // In CCM, OCB mode: must be provided by user.
288+
289+ // Logic for default auth tag length
290+ if (
291+ auth_tag_len == kNoAuthTagLength &&
292+ mode == EVP_CIPH_GCM_MODE
293+ ) {
294+ auth_tag_len = sizeof (auth_tag);
295+ }
296+ ok = EVP_CIPHER_CTX_ctrl (
266297 ctx,
267- tempBuf,
268- &finalLen) != 1 ) {
269- delete[] tempBuf;
270- throw std::runtime_error (" Failed to finalize cipher: " +
271- std::to_string (ERR_get_error ()));
298+ EVP_CTRL_AEAD_GET_TAG,
299+ auth_tag_len,
300+ reinterpret_cast <unsigned char *>(auth_tag)
301+ ) == 1 ;
302+ }
303+ }
304+
305+ if (!ok) {
306+ delete[] out;
307+ throw std::runtime_error (" Failed to finalize cipher" );
272308 }
273309
274310 // Create and return a new buffer of exact size needed
275311 return std::make_shared<NativeArrayBuffer>(
276- tempBuf ,
277- finalLen ,
278- [=]() { delete[] tempBuf ; }
312+ out ,
313+ out_len ,
314+ [=]() { delete[] out ; }
279315 );
280316}
281317
0 commit comments