Skip to content

Commit 6fe9f78

Browse files
committed
wip - GCM & final()
1 parent 08cc504 commit 6fe9f78

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

example/src/tests/cipher/cipher_tests.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import { expect } from 'chai';
1313
import { test } from '../util';
1414

1515
const SUITE = 'cipher';
16-
// const ciphers = getCiphers();
17-
const ciphers = ['AES-128-GCM'];
16+
const ciphers = getCiphers().filter((c) => c.includes('GCM'));
17+
// const ciphers = ['AES-128-GCM'];
1818
const key = randomFillSync(new Uint8Array(32));
1919
const iv = randomFillSync(new Uint8Array(16));
2020
const plaintext =

packages/react-native-quick-crypto/cpp/cipher/HybridCipher.cpp

+48-12
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)