geforkt von Mirrors/Velocity
Rewrite native crypto to use OpenSSL
OpenSSL is much more portable and optimized (important for aarch64) and most systems already have a version. Unfortunately, OpenSSL likes to break their ABI. Thankfully, Velocity's natives system is very flexible largely, so we can provide multiple versions of this crypto. Versions of the dynamically-linked crypto were compiled on CentOS 7 (still supported until 2024, uses OpenSSL 1.0.x) and Debian 9 (the oldest distro including OpenSSL 1.1.0, whose LTS supports ends in 2022). The choice of distros was intended to cover most modern distributions (2014 and afterwards). An ARM compilation (using Debian 9) will be published soon.
Dieser Commit ist enthalten in:
Ursprung
bd0455caa0
Commit
1bb84f81df
1
.gitignore
vendored
1
.gitignore
vendored
@ -91,3 +91,4 @@ native/mbedtls
|
||||
native/zlib-ng
|
||||
native/zlib-cf
|
||||
native/libdeflate
|
||||
native/src/main/resources/linux_x86_64/velocity-cipher.so
|
@ -7,16 +7,13 @@ fi
|
||||
|
||||
echo "Compiling libdeflate..."
|
||||
cd libdeflate || exit
|
||||
make
|
||||
CFLAGS="-fPIC -O2" make
|
||||
cd ..
|
||||
|
||||
# Modify as you need.
|
||||
MBEDTLS_ROOT=mbedtls
|
||||
CFLAGS="-O3 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack"
|
||||
ARCH=$(uname -m)
|
||||
mkdir -p src/main/resources/linux_$ARCH
|
||||
gcc $CFLAGS -Ilibdeflate src/main/c/jni_util.c src/main/c/jni_zlib_deflate.c src/main/c/jni_zlib_inflate.c \
|
||||
libdeflate/libdeflate.a -o src/main/resources/linux_$ARCH/velocity-compress.so
|
||||
gcc $CFLAGS -I $MBEDTLS_ROOT/include -shared $MBEDTLS_ROOT/library/aes.c $MBEDTLS_ROOT/library/aesni.c \
|
||||
$MBEDTLS_ROOT/library/platform.c $MBEDTLS_ROOT/library/platform_util.c src/main/c/jni_util.c src/main/c/jni_cipher.c \
|
||||
-o src/main/resources/linux_$ARCH/velocity-cipher.so
|
||||
gcc $CFLAGS -I $MBEDTLS_ROOT/include -shared src/main/c/jni_util.c src/main/c/jni_cipher.c \
|
||||
-o src/main/resources/linux_$ARCH/velocity-cipher.so -lcrypto
|
@ -1,81 +1,59 @@
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "jni_util.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef struct {
|
||||
mbedtls_aes_context cipher;
|
||||
byte *key;
|
||||
} velocity_cipher_context;
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_init(JNIEnv *env,
|
||||
Java_com_velocitypowered_natives_encryption_OpenSslCipherImpl_init(JNIEnv *env,
|
||||
jobject obj,
|
||||
jbyteArray key)
|
||||
jbyteArray key,
|
||||
jboolean encrypt)
|
||||
{
|
||||
velocity_cipher_context *ctx = malloc(sizeof(velocity_cipher_context));
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
throwException(env, "java/lang/OutOfMemoryError", "cipher allocate context");
|
||||
throwException(env, "java/lang/OutOfMemoryError", "allocate cipher");
|
||||
return 0;
|
||||
}
|
||||
|
||||
jsize keyLen = (*env)->GetArrayLength(env, key);
|
||||
jbyte* keyBytes = (*env)->GetPrimitiveArrayCritical(env, key, NULL);
|
||||
if (keyBytes == NULL) {
|
||||
free(ctx);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
throwException(env, "java/lang/OutOfMemoryError", "cipher get key");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mbedtls_aes_init(&ctx->cipher);
|
||||
int ret = mbedtls_aes_setkey_enc(&ctx->cipher, (byte*) keyBytes, keyLen * 8);
|
||||
if (ret != 0) {
|
||||
int result = EVP_CipherInit(ctx, EVP_aes_128_cfb8(), (byte*) keyBytes, (byte*) keyBytes,
|
||||
encrypt);
|
||||
// Release the key byte array now - we won't need it
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, key, keyBytes, 0);
|
||||
mbedtls_aes_free(&ctx->cipher);
|
||||
free(ctx);
|
||||
|
||||
throwException(env, "java/security/GeneralSecurityException", "mbedtls set aes key");
|
||||
if (result != 1) {
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
throwException(env, "java/security/GeneralSecurityException", "openssl initialize cipher");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->key = malloc(keyLen);
|
||||
if (ctx->key == NULL) {
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, key, keyBytes, 0);
|
||||
mbedtls_aes_free(&ctx->cipher);
|
||||
free(ctx);
|
||||
|
||||
throwException(env, "java/lang/OutOfMemoryError", "cipher copy key");
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->key, keyBytes, keyLen);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, key, keyBytes, 0);
|
||||
return (jlong) ctx;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_free(JNIEnv *env,
|
||||
Java_com_velocitypowered_natives_encryption_OpenSslCipherImpl_free(JNIEnv *env,
|
||||
jobject obj,
|
||||
jlong ptr)
|
||||
{
|
||||
velocity_cipher_context *ctx = (velocity_cipher_context*) ptr;
|
||||
mbedtls_aes_free(&ctx->cipher);
|
||||
free(ctx->key);
|
||||
free(ctx);
|
||||
EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *) ptr);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_process(JNIEnv *env,
|
||||
Java_com_velocitypowered_natives_encryption_OpenSslCipherImpl_process(JNIEnv *env,
|
||||
jobject obj,
|
||||
jlong ptr,
|
||||
jlong source,
|
||||
jint len,
|
||||
jlong dest,
|
||||
jboolean encrypt)
|
||||
jlong dest)
|
||||
{
|
||||
velocity_cipher_context *ctx = (velocity_cipher_context*) ptr;
|
||||
mbedtls_aes_crypt_cfb8(&ctx->cipher, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, len, ctx->key,
|
||||
(byte*) source, (byte*) dest);
|
||||
EVP_CipherUpdate((EVP_CIPHER_CTX*) ptr, (byte*) dest, &len, (byte*) source, len);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.velocitypowered.natives.encryption;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
class MbedtlsAesImpl {
|
||||
|
||||
native long init(byte[] key) throws GeneralSecurityException;
|
||||
|
||||
native void process(long ctx, long sourceAddress, int sourceLength, long destinationAddress,
|
||||
boolean encrypt);
|
||||
|
||||
native void free(long ptr);
|
||||
}
|
@ -3,10 +3,8 @@ package com.velocitypowered.natives.encryption;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.natives.util.BufferPreference;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import java.security.GeneralSecurityException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.ShortBufferException;
|
||||
|
||||
public class NativeVelocityCipher implements VelocityCipher {
|
||||
|
||||
@ -21,15 +19,13 @@ public class NativeVelocityCipher implements VelocityCipher {
|
||||
return new NativeVelocityCipher(false, key);
|
||||
}
|
||||
};
|
||||
private static final MbedtlsAesImpl impl = new MbedtlsAesImpl();
|
||||
private static final OpenSslCipherImpl impl = new OpenSslCipherImpl();
|
||||
|
||||
private final long ctx;
|
||||
private final boolean encrypt;
|
||||
private boolean disposed = false;
|
||||
|
||||
private NativeVelocityCipher(boolean encrypt, SecretKey key) throws GeneralSecurityException {
|
||||
this.encrypt = encrypt;
|
||||
this.ctx = impl.init(key.getEncoded());
|
||||
this.ctx = impl.init(key.getEncoded(), encrypt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -40,7 +36,7 @@ public class NativeVelocityCipher implements VelocityCipher {
|
||||
long base = source.memoryAddress() + source.readerIndex();
|
||||
int len = source.readableBytes();
|
||||
|
||||
impl.process(ctx, base, len, base, encrypt);
|
||||
impl.process(ctx, base, len, base);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.velocitypowered.natives.encryption;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
class OpenSslCipherImpl {
|
||||
|
||||
native long init(byte[] key, boolean encrypt) throws GeneralSecurityException;
|
||||
|
||||
native void process(long ctx, long source, int len, long dest);
|
||||
|
||||
native void free(long ptr);
|
||||
}
|
@ -80,11 +80,17 @@ public class Natives {
|
||||
public static final NativeCodeLoader<VelocityCipherFactory> cipher = new NativeCodeLoader<>(
|
||||
ImmutableList.of(
|
||||
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64,
|
||||
copyAndLoadNative("/linux_x86_64/velocity-cipher.so"),
|
||||
"mbed TLS (Linux x86_64)", NativeVelocityCipher.FACTORY),
|
||||
copyAndLoadNative("/linux_x86_64/velocity-cipher.so"), // Any local version
|
||||
"OpenSSL local (Linux x86_64)", NativeVelocityCipher.FACTORY),
|
||||
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64,
|
||||
copyAndLoadNative("/linux_x86_64/velocity-cipher-ossl11x.so"), // Debian 9
|
||||
"OpenSSL 1.1.x (Linux x86_64)", NativeVelocityCipher.FACTORY),
|
||||
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64,
|
||||
copyAndLoadNative("/linux_x86_64/velocity-cipher-ossl10x.so"), // CentOS 7
|
||||
"OpenSSL 1.0.x (Linux x86_64)", NativeVelocityCipher.FACTORY),
|
||||
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64,
|
||||
copyAndLoadNative("/linux_aarch64/velocity-cipher.so"),
|
||||
"mbed TLS (Linux aarch64)", NativeVelocityCipher.FACTORY),
|
||||
"OpenSSL (Linux aarch64)", NativeVelocityCipher.FACTORY),
|
||||
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {
|
||||
}, "Java", JavaVelocityCipher.FACTORY)
|
||||
)
|
||||
|
BIN
native/src/main/resources/linux_x86_64/velocity-cipher-ossl10x.so
Ausführbare Datei
BIN
native/src/main/resources/linux_x86_64/velocity-cipher-ossl10x.so
Ausführbare Datei
Binäre Datei nicht angezeigt.
BIN
native/src/main/resources/linux_x86_64/velocity-cipher-ossl11x.so
Ausführbare Datei
BIN
native/src/main/resources/linux_x86_64/velocity-cipher-ossl11x.so
Ausführbare Datei
Binäre Datei nicht angezeigt.
Binäre Datei nicht angezeigt.
@ -30,7 +30,6 @@ class VelocityCipherTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void nativeIntegrityCheck() throws GeneralSecurityException {
|
||||
VelocityCipherFactory factory = Natives.cipher.get();
|
||||
if (factory == JavaVelocityCipher.FACTORY) {
|
||||
@ -39,11 +38,6 @@ class VelocityCipherTest {
|
||||
check(factory, Unpooled::directBuffer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void javaIntegrityCheckDirect() throws GeneralSecurityException {
|
||||
check(JavaVelocityCipher.FACTORY, Unpooled::directBuffer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void javaIntegrityCheckHeap() throws GeneralSecurityException {
|
||||
check(JavaVelocityCipher.FACTORY, Unpooled::buffer);
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren