From 2e80bf30ddab0f29c49c959a03e592e6510640ef Mon Sep 17 00:00:00 2001 From: md_5 Date: Wed, 12 Feb 2014 17:36:58 +1100 Subject: [PATCH] Various improvements to native cipher so that it now actually destroys Java in terms of speed. Closes #871 - thanks @ninja- --- native/src/main/c/NativeCipherImpl.c | 48 +++++++++++------- .../main/c/net_md_5_bungee_NativeCipherImpl.h | 16 ++++-- .../java/net/md_5/bungee/NativeCipher.java | 34 +++++-------- .../net/md_5/bungee/NativeCipherImpl.java | 17 +++++-- native/src/main/resources/native-cipher.so | Bin 8277 -> 8401 bytes 5 files changed, 69 insertions(+), 46 deletions(-) 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 03d70f6d70920cc175577d79108a1e12fdec506d..cece627927e62de2e2edf4c8b08d00c4ebc91f58 100755 GIT binary patch delta 2459 zcmZuzeN0nV6u(Mk3ZaG1NNqj6pO*GnGQwP}V(wKq zz#ZB6W<2`x;Bxus*ZU9NlX!ik`A+adVxWVb4V{B-gg!eY=StZ=fp8LZJM`c1WZ&ZP zAI^Sv_vnGTRoCy`Xm2c9JzRHcple2)`su!S>z(RB9N~)cbx1&CCh&Nwoq=~7XzkqV zxP$j_5qyq!8BRW7i-^n>g3iTNQ{6hy%_AO$KQya|4Ds1e7K*cE%RocgL+FIx$an{3 z5jq0)5^|!AlFXP49H6`dHO}D^xLxOp?FAz`nvk(R$b88}*q)P{lk(ZOruM}w5l zLKAG91DYZn-rBlrXLwIEvO5|Mqwuz!+oCAE1ptKu^*CSOp?hufetcYCmqS#6^{91o z>!!B-_>R6D-_m#Rl~uUGP=fau>=8Yz+1wxb4u^QOo2H477vy6-U%CjgolSak}GaZrT7q^2wkIvw6gR4?zDa_``M2XnmL=)^K#3oYXL;d+iiHk9o>;<-S zskf52XI455k4-XCJ|2o1lFNWr5|_*)RE^TF*vv9YFUW(ZwZsQ+L~bF<)I=KE0t=Bz zxO(PI_JyAmB51P^wBtWn~m$Co$Df?k;GCN}>)b<+KD(dC*Br%WI zv;&FuzMv#(OysQrhL2_|oi*z~O0IU(|jlhyhL3Lt7lmA_RlfQWca*rYS<}ZqRHTm;nm}m9&hSXJf zc{;gGE6b!q*Obm^nc4dJ#i07*s>)I8`D^9-DLW*{yUcW{5tJaX{QLZw6P;e&m$o;nVe_R$gND8cFE>sM7V%(t=J6t^ok|i z03H@S+&6eeEU}fd+gQ7lTa0*~wW8DwYeX8%&Mtzio}g(aPvLg!=~s;`11H0U43{um z&2T-#Eeu2b0cnuq6fD?QaI-jI^W=KT352HM09JvWB1;EN!^LgWLs+nTEcA?m zEo4w@UxF{#B}h@VdjxGR#_+IxY3?-3RKqwH@;pyUs#aQ|Cgyo8+O-X{_fg)G+-C|X z9tGDVyW2H<*e^I@92df>(}QQ7GQQ!I1+APkV$QXKYs7wdCUA#qh2VA54ABKV>RKu! zi!)LR3+_*0xq93#ZVC^(9Xca&;~78`YN2RG<+wE8p@V`-(SoJ{UHMuDnQ<~t9qfyf zxC5+nP#;ARB>_)El(_{CofAPs1!3$ilu9eWg@-%&1Y0X@96#eH@OXg>GDsD8cv-*& zg<&oWe^A(*ucfFtm|#nC$bmw5rtk<)rm*NRZY-9tTx^cbEz`?jgFUZIZw3B&WqJp* zpIbnWQ~PJjcds_SK*JM}R=LNBg8Y{d?otz&&i>xwQ@jABHN5$~NHju9YbhzVPMk-83-R#CagN$ffn;=0D|8vW zbUmCmIOsbnV^{k>sr@HeUkIZ8T=Y}WF@e2&45^lHt4ni5E^yw*c{AsmFmfxglXX@% zXEfN3!2Be*;cI;KS=GLXG|sROXnq=J4IEP)&EA}rog6a61LFP(35PeoynS1ESFC+! zEF6Y_sTZ!8>S3kO1=j?7$UwByW0}{4V)h??*lAGmv>Fg0ZnWF&+JdVX$r|KXW8>v~ zoayc-w&LL#$P3V(;qXWKmZx*wY>?=w^6`$$x32T@;QJX?+R=T-EcXhh&2A#Uo{R~T z^*B}T9x`84ojiD@pZN$)((^vXcV1a7_Lv@Fzj&NiJ&s`}eZ zXIoDtRQ)K^P0frrp%RA}Auv6Ty4)wkk&ydp_93*$3#Mh|w%k1}?lFWeV#Fpkh!OuD zN{_RE(EfSNezh4sG?#aLpUDh_a(D9j zKk0Pm-U=&;70SIv|42}okd@zL;(grCcwMt=j!nlxGKW$oKT*9so z6G|s~k`c!-;3#4nZt5&z6fsF)B5S_jLz5`vWM4f0oVvxn+!^VK zauy7ZXIl+0o_&9{{;}&HH}lIH|5Mc8cmz`;G|eaqwuBZ zrE!=N%kl>>ZLH~c+?W7!^D4^+*msHz)4{GB{&N#@kLyv`k@uc|6QA`8#{(SS;&_JR z1&;Dyll2Qqmw_#RDg6eT^1U|oG}sF4RIo*%AK55hUdQ<`imV=#je3aV_4JRTjRU@P=Ks8D*PqR>?6&C)MI%;2HI#kN`X2u5)# z;e|}c8-uo@4oYR{w|g!6#U#Usy$X_cH@F=h+6WDfrSw%$97`>pVr}yWVboD&Nt9~Z zX|NUdIQ7J6oc1;n0TXq;*g*&IU1ZE8V=9`-0Ng?yuXV6F9k_ac*CJ1` zx;4U-%L`{+R`8WH(Ja_k(uy(PDskX?f0i6Eu$<31EX^!xxp?b7s+ca}{LEsy8EmBv th?biD3I5~iWpe;$Sjp_Nd0h2`X&k&>dd47<@Wz+gW9=loW!sh*`47pb(<%S}