in csrc/aes_gcm.cpp [352:425]
JNIEXPORT jint JNICALL Java_com_amazon_corretto_crypto_provider_AesGcmSpi_oneShotDecrypt(
JNIEnv *pEnv,
jclass,
jlong ctxPtr,
jlongArray ctxOut,
jbyteArray inputArray,
jint inoffset,
jint inlen,
jbyteArray resultArray,
jint resultOffset,
jint tagLen,
jbyteArray keyArray,
jbyteArray ivArray,
jbyteArray aadBuffer,
jint aadSize
) {
try {
raii_env env(pEnv);
java_buffer input = java_buffer::from_array(env, inputArray, inoffset, inlen);
java_buffer result = java_buffer::from_array(env, resultArray, resultOffset);
java_buffer iv = java_buffer::from_array(env, ivArray);
raii_cipher_ctx ctx;
if (ctxPtr) {
ctx.borrow(reinterpret_cast<EVP_CIPHER_CTX *>(ctxPtr));
jni_borrow ivBorrow(env, iv, "iv");
if (unlikely(!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, ivBorrow.data(), NATIVE_MODE_DECRYPT))) {
throw java_ex::from_openssl(EX_RUNTIME_CRYPTO, "Failed to set IV");
}
} else {
ctx.init();
EVP_CIPHER_CTX_init(ctx);
java_buffer key = java_buffer::from_array(env, keyArray);
initContext(env, ctx, NATIVE_MODE_DECRYPT, key, iv);
}
// Decrypt mode: Set the tag before we decrypt
if (unlikely(tagLen > 16 || tagLen < 0)) {
throw java_ex(EX_ILLEGAL_ARGUMENT, "Bad tag length");
}
if (unlikely(inlen < tagLen)) {
throw java_ex(EX_BADTAG, "Input too short - need tag");
}
SecureBuffer<uint8_t, 16> tag;
input.get_bytes(env, tag.buf, input.len() - tagLen, tagLen);
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tagLen, tag.buf)) {
throw java_ex::from_openssl(EX_RUNTIME_CRYPTO, "Failed to set GCM tag");
}
input = input.subrange(0, input.len() - tagLen);
if (aadSize != 0) {
updateAAD_loop(env, ctx, java_buffer::from_array(env, aadBuffer, 0, aadSize));
}
int outoffset = updateLoop(env, result, input, ctx);
outoffset += cryptFinish(env, NATIVE_MODE_DECRYPT, result.subrange(outoffset), tagLen, ctx);
if (!ctxPtr && ctxOut) {
// Context is new, but caller does want it back
jlong tmpPtr = reinterpret_cast<jlong>(ctx.take());
env->SetLongArrayRegion(ctxOut, 0, 1, &tmpPtr);
}
return outoffset;
} catch (java_ex &ex) {
ex.throw_to_java(pEnv);
return -1;
}
}