diff --git a/native/src/main/c/NativeCipherImpl.c b/native/src/main/c/NativeCipherImpl.c index 6e35aa68..e5b7a7b6 100644 --- a/native/src/main/c/NativeCipherImpl.c +++ b/native/src/main/c/NativeCipherImpl.c @@ -3,54 +3,66 @@ #include #include #include +#include #define BYTE unsigned char -jlong Java_net_md_15_bungee_NativeCipherImpl_init +jlong Java_net_md_15_bungee_NativeCipherImpl_initKey (JNIEnv* env, jobject obj, jbyteArray key) { AES_KEY *aes_key = malloc(sizeof(AES_KEY)); - jboolean isKeyCopy; - BYTE *key_bytes = (BYTE*)(*env)->GetByteArrayElements(env, key, &isKeyCopy); + jboolean isFieldCopy; + BYTE *key_bytes = (BYTE*)(*env)->GetByteArrayElements(env, key, &isFieldCopy); int key_length = (*env)->GetArrayLength(env, key) * 8; // in bits AES_set_encrypt_key(key_bytes, key_length, aes_key); - if (isKeyCopy) { + if (isFieldCopy) { (*env)->ReleaseByteArrayElements(env, key, (jbyte*)key_bytes, JNI_ABORT); } + return (long) aes_key; } +jlong Java_net_md_15_bungee_NativeCipherImpl_initIV +(JNIEnv* env, jobject obj, jbyteArray iv) +{ + jboolean isFieldCopy; + BYTE *iv_bytes = (BYTE*)(*env)->GetByteArrayElements(env, iv, &isFieldCopy); + int iv_length = (*env)->GetArrayLength(env, iv); + + BYTE* jni_iv = malloc(iv_length); + + memcpy(jni_iv, iv_bytes, iv_length); + + if (isFieldCopy) { + (*env)->ReleaseByteArrayElements(env, iv, (jbyte*)iv_bytes, JNI_ABORT); + } + + return (long) jni_iv; +} void Java_net_md_15_bungee_NativeCipherImpl_free -(JNIEnv* env, jobject obj, jlong key) +(JNIEnv* env, jobject obj, jlong key, jlong iv) { free((AES_KEY*)key); + free((BYTE*)iv); } void Java_net_md_15_bungee_NativeCipherImpl_cipher -(JNIEnv* env, jobject obj, jboolean forEncryption, jlong key, jbyteArray iv, jlong in, jlong out, jint length) +(JNIEnv* env, jobject obj, jboolean forEncryption, jlong key, jlong iv, jlong in, jlong out, jint length) { AES_KEY *aes_key = (AES_KEY*)key; - size_t buffer_length = (size_t) length; - BYTE *input = (BYTE*) in; - BYTE *output = (BYTE*) out; - - jboolean isCopy; - BYTE *iv_bytes = (BYTE*)(*env)->GetByteArrayElements(env, iv, &isCopy); + BYTE *input = (BYTE*) in; + BYTE *output = (BYTE*) out; + BYTE* jni_iv = (BYTE*) iv; AES_cfb8_encrypt( input, // input buffer output, // output buffer buffer_length, // readable bytes aes_key, // encryption key - iv_bytes, // IV + jni_iv, // IV NULL, // not needed forEncryption ? AES_ENCRYPT : AES_DECRYPT // encryption mode ); - - // IV has changed, let's copy it back - if (isCopy) { - (*env)->ReleaseByteArrayElements(env, iv, (jbyte*)iv_bytes, 0); - } } diff --git a/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h b/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h index 87e30b03..47d0637d 100644 --- a/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h +++ b/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h @@ -9,10 +9,17 @@ extern "C" { #endif /* * Class: net_md_5_bungee_NativeCipherImpl - * Method: init + * Method: init_key * Signature: ([B)J */ -JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init +JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_initKey + (JNIEnv *, jobject, jbyteArray); +/* + * Class: net_md_5_bungee_NativeCipherImpl + * Method: init_iv + * Signature: ([B)J + */ +JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_initIV (JNIEnv *, jobject, jbyteArray); /* @@ -21,7 +28,7 @@ JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init * Signature: (J)V */ JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free - (JNIEnv *, jobject, jlong); + (JNIEnv *, jobject, jlong, jlong); /* * Class: net_md_5_bungee_NativeCipherImpl @@ -29,9 +36,10 @@ JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free * Signature: (ZJ[BJJI)V */ JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_cipher - (JNIEnv *, jobject, jboolean, jlong, jbyteArray, jlong, jlong, jint); + (JNIEnv *, jobject, jboolean, jlong, jlong, jlong, jlong, jint); #ifdef __cplusplus } #endif #endif + diff --git a/native/src/main/java/net/md_5/bungee/NativeCipher.java b/native/src/main/java/net/md_5/bungee/NativeCipher.java index 10e15bf8..a521c447 100644 --- a/native/src/main/java/net/md_5/bungee/NativeCipher.java +++ b/native/src/main/java/net/md_5/bungee/NativeCipher.java @@ -16,13 +16,12 @@ public class NativeCipher implements BungeeCipher { @Getter - private final NativeCipherImpl nativeCipher = new NativeCipherImpl(); - private boolean forEncryption; - private byte[] iv; - /*============================================================================*/ + private final static NativeCipherImpl nativeCipher = new NativeCipherImpl(); private static boolean loaded; - - private long pointer; + /*============================================================================*/ + private boolean forEncryption; + private long keyPointer; + private long ivPointer; public static boolean isSupported() { @@ -59,23 +58,18 @@ public class NativeCipher implements BungeeCipher @Override public void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException { - if ( pointer != 0 ) - { - nativeCipher.free( pointer ); - } + nativeCipher.free( this.keyPointer, this.ivPointer ); this.forEncryption = forEncryption; - this.iv = key.getEncoded(); // initialize the IV - this.pointer = nativeCipher.init( key.getEncoded() ); + + byte[] encoded = key.getEncoded(); + this.keyPointer = nativeCipher.initKey( encoded ); + this.ivPointer = nativeCipher.initIV( encoded ); } @Override public void free() { - if ( pointer != 0 ) - { - nativeCipher.free( pointer ); - pointer = 0; - } + nativeCipher.free( keyPointer, ivPointer ); } @Override @@ -84,8 +78,8 @@ public class NativeCipher implements BungeeCipher // Smoke tests in.memoryAddress(); out.memoryAddress(); - Preconditions.checkState( pointer != 0, "Invalid pointer to AES key!" ); - Preconditions.checkState( iv != null, "Invalid IV!" ); + Preconditions.checkState( keyPointer != 0, "Invalid pointer to AES key!" ); + Preconditions.checkState( ivPointer != 0, "Invalid pointer to IV!" ); // Store how many bytes we can cipher int length = in.readableBytes(); @@ -93,7 +87,7 @@ public class NativeCipher implements BungeeCipher out.ensureWritable( length ); // Cipher the bytes - nativeCipher.cipher( forEncryption, pointer, iv, in.memoryAddress() + in.readerIndex(), out.memoryAddress() + out.writerIndex(), length ); + nativeCipher.cipher( forEncryption, keyPointer, ivPointer, in.memoryAddress() + in.readerIndex(), out.memoryAddress() + out.writerIndex(), length ); // Go to the end of the buffer, all bytes would of been read in.readerIndex( in.writerIndex() ); diff --git a/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java b/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java index 261a84ec..072a93e6 100644 --- a/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java +++ b/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java @@ -9,24 +9,33 @@ class NativeCipherImpl * @param key the key to for encryption * @return the pointer to key */ - native long init(byte[] key); + native long initKey(byte[] key); + + /** + * Initializes the iv. + * + * @param iv the iv + * @return the pointer to iv + */ + native long initIV(byte[] iv); /** * Frees the key. * * @param key the pointer to key + * @param iv the pointer to iv */ - native void free(long key); + native void free(long key, long iv); /** * This method will encrypt some data in AES-CFB8 using the specified key. * * @param forEncryption encryption / decryption mode * @param key the pointer to key - * @param iv the iv to use + * @param iv the pointer to iv * @param in the starting memory address for reading data * @param out the starting memory address for writing data * @param length the length of data to read / write */ - native void cipher(boolean forEncryption, long key, byte[] iv, long in, long out, int length); + native void cipher(boolean forEncryption, long key, long iv, long in, long out, int length); } diff --git a/native/src/main/resources/native-cipher.so b/native/src/main/resources/native-cipher.so index 03d70f6d..cece6279 100755 Binary files a/native/src/main/resources/native-cipher.so and b/native/src/main/resources/native-cipher.so differ