native.intel.jni.gcm_jni.c Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-lts8on Show documentation
Show all versions of bcprov-lts8on Show documentation
The Long Term Stable (LTS) Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains the JCA/JCE provider and low-level API for the BC LTS version 2.73.7 for Java 8 and later.
#include
#include "org_bouncycastle_crypto_engines_AESNativeGCM.h"
#include "../gcm/gcm.h"
#include "../../jniutil/exceptions.h"
#include "../../jniutil/bytearrays.h"
#include "../../jniutil/jni_asserts.h"
#include "../../jniutil/bytearraycritical.h"
void handle_gcm_result(JNIEnv *env, gcm_err *err) {
if (err == NULL) {
return;
}
switch (err->type) {
case ILLEGAL_STATE:
throw_java_invalid_state(env, err->msg);
break;
case ILLEGAL_ARGUMENT:
throw_java_illegal_argument(env, err->msg);
break;
case ILLEGAL_CIPHER_TEXT:
throw_bc_invalid_ciphertext_exception(env, err->msg);
break;
case OUTPUT_LENGTH:
throw_bc_output_length_exception(env, err->msg);
break;
default:
throw_java_invalid_state(env, "unknown error from GCM");
break;
}
gcm_err_free(err);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: reset
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_reset
(JNIEnv *env, jobject o, jlong ref) {
gcm_ctx *ctx = (gcm_ctx *) ref;
gcm_reset(ctx, false);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: initNative
* Signature: (JZ[B[B[BI)V
*/
JNIEXPORT void JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_initNative
(JNIEnv *env, jclass cl, jlong ref, jboolean encryption, jbyteArray key_, jbyteArray iv_, jbyteArray ad_,
jint macSizeInBits) {
gcm_err *err = NULL;
gcm_ctx *ctx = (gcm_ctx *) ref;
java_bytearray_ctx key, iv, ad;
init_bytearray_ctx(&key);
init_bytearray_ctx(&iv);
init_bytearray_ctx(&ad);
if (macSizeInBits < 32 || macSizeInBits > 128 || macSizeInBits % 8 != 0) {
throw_java_illegal_argument(env, "invalid value for MAC size");
goto exit;
}
if (!load_bytearray_ctx(&key, env, key_)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid key array");
goto exit;
}
if (!load_bytearray_ctx(&iv, env, iv_)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid iv array");
goto exit;
}
if (!load_bytearray_ctx(&ad, env, ad_)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid ad array");
goto exit;
}
if (!aes_keysize_is_valid_and_not_null(env, &key)) {
goto exit;
}
if (!bytearray_not_null(&iv, "iv was null", env)) {
goto exit;
}
if (iv.size < 12) {
throw_java_illegal_argument(env, "IV must be at least 12 bytes");
goto exit;
}
err = gcm_init(
ctx,
encryption == JNI_TRUE,
key.bytearray,
key.size,
iv.bytearray,
iv.size,
ad.bytearray,
ad.size,
(uint32_t) macSizeInBits);
exit:
release_bytearray_ctx(&key);
release_bytearray_ctx(&iv);
release_bytearray_ctx(&ad);
handle_gcm_result(env, err);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: makeInstance
* Signature: (IZ)J
*/
JNIEXPORT jlong JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_makeInstance
(JNIEnv *env, jclass cl, jint i, jboolean ignored) {
gcm_ctx *gcm = gcm_create_ctx();
return (jlong) gcm;
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: dispose
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_dispose
(JNIEnv *env, jclass jc, jlong ref) {
gcm_ctx *ctx = (gcm_ctx *) ref;
gcm_free(ctx);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: processAADByte
* Signature: (JB)V
*/
JNIEXPORT void JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_processAADByte
(JNIEnv *env, jclass cl, jlong ref, jbyte aadByte) {
gcm_ctx *ctx = (gcm_ctx *) ref;
gcm_process_aad_byte(ctx, (uint8_t) aadByte);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: processAADBytes
* Signature: (J[BII)V
*/
JNIEXPORT void JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_processAADBytes
(JNIEnv *env, jclass cl, jlong ref, jbyteArray aad_, jint offset, jint len) {
gcm_ctx *ctx = (gcm_ctx *) ref;
java_bytearray_ctx aad;
init_bytearray_ctx(&aad);
if (!load_bytearray_ctx(&aad, env, aad_)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid aad array");
goto exit;
}
if (!bytearray_not_null(&aad, "aad was null", env)) {
goto exit;
}
if (!bytearray_offset_and_len_are_in_range(&aad, offset, len, env)) {
goto exit;
}
gcm_process_aad_bytes(ctx, aad.bytearray + offset, (size_t) len);
exit:
release_bytearray_ctx(&aad);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: processByte
* Signature: (JB[BI)I
*/
JNIEXPORT jint JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_processByte
(JNIEnv *env, jclass cl, jlong ref, jbyte byte, jbyteArray out, jint offset) {
gcm_err *err = NULL;
critical_bytearray_ctx output;
init_critical_ctx(&output, env, out);
size_t written = 0;
gcm_ctx *ctx = (gcm_ctx *) ref;
if (offset < 0) {
throw_java_illegal_argument(env, "offset is negative");
goto exit;
}
if (output.array != NULL) {
if (!critical_offset_is_in_range(&output, offset, env)) {
goto exit;
}
}
if (!load_critical_ctx(&output)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid output array");
goto exit;
}
// NULL is a valid destination if the caller is not expecting any output
// GCM will return an error if there is a decryption result is generated.
uint8_t *dest = output.critical == NULL ? NULL : output.critical + offset;
size_t outputLen = output.array == NULL ? 0 : output.size - (size_t) offset;
err = gcm_process_byte(
ctx,
(uint8_t) byte,
dest,
outputLen, &written);
exit:
release_critical_ctx(&output);
handle_gcm_result(env, err);
return (jint) written;
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: processBytes
* Signature: (J[BII[BI)I
*/
JNIEXPORT jint JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_processBytes
(JNIEnv *env, jclass cl, jlong ref, jbyteArray in, jint inOff, jint len, jbyteArray out, jint outoff) {
gcm_err *err = NULL;
gcm_ctx *ctx = (gcm_ctx *) ref;
size_t written = 0;
critical_bytearray_ctx input, output;
init_critical_ctx(&output, env, out);
init_critical_ctx(&input, env, in);
if (!critical_not_null(&input, "input was null", env)) {
goto exit;
}
if (outoff < 0) {
throw_java_illegal_argument(env, "output offset is negative");
goto exit;
}
if (output.array != NULL) {
if (!critical_offset_is_in_range(&output, outoff, env)) {
goto exit;
}
}
if (!critical_offset_and_len_are_in_range(&input, inOff, len, env)) {
goto exit;
}
if (!load_critical_ctx(&output)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid output array");
goto exit;
}
if (!load_critical_ctx(&input)) {
release_critical_ctx(&output);
throw_java_invalid_state(env, "unable to obtain ptr to valid input array");
goto exit;
}
// NULL is a valid destination if the caller is not expecting any output
// GCM will return an error if there is a decryption result is generated.
uint8_t *dest = output.critical == NULL ? NULL : output.critical + outoff;
size_t outLen = output.array == NULL ? 0 : output.size - (size_t) outoff;
uint8_t *src = input.critical + inOff;
err = gcm_process_bytes(ctx,
src,
(size_t) len,
dest,
outLen,
&written);
exit:
release_critical_ctx(&input);
release_critical_ctx(&output);
handle_gcm_result(env, err);
return (jint) written;
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: doFinal
* Signature: (J[BI)I
*/
JNIEXPORT jint JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_doFinal
(JNIEnv *env, jclass cl, jlong ref, jbyteArray out, jint offset) {
gcm_err *err = NULL;
size_t written = 0;
gcm_ctx *ctx = (gcm_ctx *) ref;
critical_bytearray_ctx output;
init_critical_ctx(&output, env, out);
if (!critical_not_null(&output, "output was null", env)) {
goto exit;
}
if (!critical_offset_is_in_range(&output, offset, env)) {
goto exit;
}
if (!load_critical_ctx(&output)) {
throw_java_invalid_state(env, "unable to obtain ptr to valid output array");
goto exit;
}
uint8_t *dest = output.critical + offset;
size_t len = output.size - (size_t) offset;
err = gcm_doFinal(ctx, dest, len, &written);
exit:
release_critical_ctx(&output);
handle_gcm_result(env, err);
return (jint) written;
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: getUpdateOutputSize
* Signature: (JI)I
*/
JNIEXPORT jint JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_getUpdateOutputSize
(JNIEnv *env, jclass cl, jlong ref, jint len) {
gcm_ctx *ctx = (gcm_ctx *) ref;
if (len < 0) {
throw_java_illegal_argument(env, "len is negative");
return 0;
}
return (jint) gcm_get_update_output_size(ctx, (size_t) len);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: getOutputSize
* Signature: (JI)I
*/
JNIEXPORT jint JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_getOutputSize
(JNIEnv *env, jclass jo, jlong ref, jint len) {
gcm_ctx *ctx = (gcm_ctx *) ref;
if (len < 0) {
throw_java_illegal_argument(env, "len is negative");
return 0;
}
return (jint) gcm_get_output_size(ctx, (size_t) len);
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: getMac
* Signature: (J)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_getMac
(JNIEnv *env, jclass cl, jlong ref) {
gcm_ctx *ctx = (gcm_ctx *) ref;
size_t macBlockLen = gcm_getMac(ctx, NULL);
jbyteArray out = (*env)->NewByteArray(env, (jint) macBlockLen);
if (out == NULL) {
throw_java_invalid_state(env, "unable to create output array");
return NULL;
}
java_bytearray_ctx out_ctx;
init_bytearray_ctx(&out_ctx);
if (!load_bytearray_ctx(&out_ctx, env, out)) {
throw_java_invalid_state(env, "unable to obtain ptr to output array");
goto exit;
}
gcm_getMac(ctx, out_ctx.bytearray);
exit:
release_bytearray_ctx(&out_ctx);
return out;
}
/*
* Class: org_bouncycastle_crypto_engines_AESNativeGCM
* Method: setBlocksRemainingDown
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_org_bouncycastle_crypto_engines_AESNativeGCM_setBlocksRemainingDown
(JNIEnv *env, jobject oj, jlong ref, jlong downValue) {
//
// This method is not part of the public api, it is used in testing.
//
gcm_ctx *ctx = (gcm_ctx *) ref;
if (downValue < 0) {
throw_java_illegal_argument(env, "attempt to increment blocks remaining");
return;
}
if (ctx->totalBytes > 0) {
throw_java_illegal_argument(env, "data has been written");
return;
}
if (ctx->blocksRemaining - downValue > ctx->blocksRemaining) {
throw_java_illegal_argument(env, "attempt to increment blocks remaining");
return;
}
ctx->blocksRemaining -= downValue;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy