diff --git a/native/compile-native.sh b/native/compile-native.sh index 45e1164f..1baca889 100755 --- a/native/compile-native.sh +++ b/native/compile-native.sh @@ -1,3 +1,3 @@ #!/bin/sh -gcc -shared -fPIC -O3 -Werror -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ src/main/c/NativeCipherImpl.c -o src/main/resources/native-cipher.so -lcrypto +g++ -shared -fPIC -O3 -Werror -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ src/main/c/NativeCipherImpl.cpp -o src/main/resources/native-cipher.so -lcrypto diff --git a/native/src/main/c/NativeCipherImpl.c b/native/src/main/c/NativeCipherImpl.c deleted file mode 100644 index 6e35aa68..00000000 --- a/native/src/main/c/NativeCipherImpl.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "net_md_5_bungee_NativeCipherImpl.h" -#include -#include -#include -#include -#define BYTE unsigned char - -jlong Java_net_md_15_bungee_NativeCipherImpl_init -(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); - int key_length = (*env)->GetArrayLength(env, key) * 8; // in bits - - AES_set_encrypt_key(key_bytes, key_length, aes_key); - - if (isKeyCopy) { - (*env)->ReleaseByteArrayElements(env, key, (jbyte*)key_bytes, JNI_ABORT); - } - return (long) aes_key; -} -void Java_net_md_15_bungee_NativeCipherImpl_free -(JNIEnv* env, jobject obj, jlong key) -{ - free((AES_KEY*)key); -} -void Java_net_md_15_bungee_NativeCipherImpl_cipher -(JNIEnv* env, jobject obj, jboolean forEncryption, jlong key, jbyteArray 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); - - AES_cfb8_encrypt( - input, // input buffer - output, // output buffer - buffer_length, // readable bytes - aes_key, // encryption key - iv_bytes, // 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/NativeCipherImpl.cpp b/native/src/main/c/NativeCipherImpl.cpp new file mode 100644 index 00000000..1c2981dd --- /dev/null +++ b/native/src/main/c/NativeCipherImpl.cpp @@ -0,0 +1,22 @@ +#include +#include "net_md_5_bungee_NativeCipherImpl.h" + +typedef unsigned char byte; + +jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init(JNIEnv* env, jobject obj, jboolean forEncryption, jbyteArray key) { + jbyte *keyBytes = env->GetByteArrayElements(key, NULL); + + EVP_CIPHER_CTX *cipherCtx = new EVP_CIPHER_CTX(); + EVP_CipherInit(cipherCtx, EVP_aes_128_cfb8(), (byte*) keyBytes, (byte*) keyBytes, forEncryption); + + env->ReleaseByteArrayElements(key, keyBytes, JNI_ABORT); + return (jlong) cipherCtx; +} + +void Java_net_md_15_bungee_NativeCipherImpl_free(JNIEnv* env, jobject obj, jlong ctx) { + EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*) ctx); +} + +void Java_net_md_15_bungee_NativeCipherImpl_cipher(JNIEnv* env, jobject obj, jlong ctx, jlong in, jlong out, jint length) { + EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, (byte*) out, &length, (byte*) in, length); +} 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..c4187cc9 100644 --- a/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h +++ b/native/src/main/c/net_md_5_bungee_NativeCipherImpl.h @@ -10,10 +10,10 @@ extern "C" { /* * Class: net_md_5_bungee_NativeCipherImpl * Method: init - * Signature: ([B)J + * Signature: (Z[B)J */ JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init - (JNIEnv *, jobject, jbyteArray); + (JNIEnv *, jobject, jboolean, jbyteArray); /* * Class: net_md_5_bungee_NativeCipherImpl @@ -26,10 +26,10 @@ JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free /* * Class: net_md_5_bungee_NativeCipherImpl * Method: cipher - * Signature: (ZJ[BJJI)V + * Signature: (JJJI)V */ JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_cipher - (JNIEnv *, jobject, jboolean, jlong, jbyteArray, jlong, jlong, jint); + (JNIEnv *, jobject, jlong, jlong, jlong, jint); #ifdef __cplusplus } 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 3dc6920a..96f9c83c 100644 --- a/native/src/main/java/net/md_5/bungee/NativeCipher.java +++ b/native/src/main/java/net/md_5/bungee/NativeCipher.java @@ -17,12 +17,9 @@ public class NativeCipher implements BungeeCipher @Getter private final NativeCipherImpl nativeCipher = new NativeCipherImpl(); - private boolean forEncryption; - private byte[] iv; /*============================================================================*/ private static boolean loaded; - - private long pointer; + private long ctx; public static boolean isSupported() { @@ -62,22 +59,18 @@ public class NativeCipher implements BungeeCipher public void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException { Preconditions.checkArgument( key.getEncoded().length == 16, "Invalid key size" ); - if ( pointer != 0 ) - { - nativeCipher.free( pointer ); - } - this.forEncryption = forEncryption; - this.iv = key.getEncoded(); // initialize the IV - this.pointer = nativeCipher.init( key.getEncoded() ); + free(); + + this.ctx = nativeCipher.init( forEncryption, key.getEncoded() ); } @Override public void free() { - if ( pointer != 0 ) + if ( ctx != 0 ) { - nativeCipher.free( pointer ); - pointer = 0; + nativeCipher.free( ctx ); + ctx = 0; } } @@ -87,8 +80,7 @@ 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( ctx != 0, "Invalid pointer to AES key!" ); // Store how many bytes we can cipher int length = in.readableBytes(); @@ -96,7 +88,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( ctx, 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..2167b1c4 100644 --- a/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java +++ b/native/src/main/java/net/md_5/bungee/NativeCipherImpl.java @@ -3,30 +3,9 @@ package net.md_5.bungee; class NativeCipherImpl { - /** - * Initializes the key. - * - * @param key the key to for encryption - * @return the pointer to key - */ - native long init(byte[] key); + native long init(boolean forEncryption, byte[] key); - /** - * Frees the key. - * - * @param key the pointer to key - */ - native void free(long key); + native void free(long ctx); - /** - * 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 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(long ctx, 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..9fd92de9 100755 Binary files a/native/src/main/resources/native-cipher.so and b/native/src/main/resources/native-cipher.so differ