@@ -258,24 +258,60 @@ HybridCipher::final() {
258
258
throw std::runtime_error (" Cipher not initialized. Did you call setArgs()?" );
259
259
}
260
260
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) ;
263
263
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 (
266
297
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" );
272
308
}
273
309
274
310
// Create and return a new buffer of exact size needed
275
311
return std::make_shared<NativeArrayBuffer>(
276
- tempBuf ,
277
- finalLen ,
278
- [=]() { delete[] tempBuf ; }
312
+ out ,
313
+ out_len ,
314
+ [=]() { delete[] out ; }
279
315
);
280
316
}
281
317
0 commit comments