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-ng
|
||||||
native/zlib-cf
|
native/zlib-cf
|
||||||
native/libdeflate
|
native/libdeflate
|
||||||
|
native/src/main/resources/linux_x86_64/velocity-cipher.so
|
@ -7,16 +7,13 @@ fi
|
|||||||
|
|
||||||
echo "Compiling libdeflate..."
|
echo "Compiling libdeflate..."
|
||||||
cd libdeflate || exit
|
cd libdeflate || exit
|
||||||
make
|
CFLAGS="-fPIC -O2" make
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Modify as you need.
|
|
||||||
MBEDTLS_ROOT=mbedtls
|
|
||||||
CFLAGS="-O3 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack"
|
CFLAGS="-O3 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack"
|
||||||
ARCH=$(uname -m)
|
ARCH=$(uname -m)
|
||||||
mkdir -p src/main/resources/linux_$ARCH
|
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 \
|
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
|
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 \
|
gcc $CFLAGS -I $MBEDTLS_ROOT/include -shared src/main/c/jni_util.c src/main/c/jni_cipher.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 -lcrypto
|
||||||
-o src/main/resources/linux_$ARCH/velocity-cipher.so
|
|
@ -1,81 +1,59 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <mbedtls/aes.h>
|
#include <openssl/evp.h>
|
||||||
#include "jni_util.h"
|
#include "jni_util.h"
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
mbedtls_aes_context cipher;
|
|
||||||
byte *key;
|
|
||||||
} velocity_cipher_context;
|
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL
|
||||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_init(JNIEnv *env,
|
Java_com_velocitypowered_natives_encryption_OpenSslCipherImpl_init(JNIEnv *env,
|
||||||
jobject obj,
|
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) {
|
if (ctx == NULL) {
|
||||||
throwException(env, "java/lang/OutOfMemoryError", "cipher allocate context");
|
throwException(env, "java/lang/OutOfMemoryError", "allocate cipher");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsize keyLen = (*env)->GetArrayLength(env, key);
|
jsize keyLen = (*env)->GetArrayLength(env, key);
|
||||||
jbyte* keyBytes = (*env)->GetPrimitiveArrayCritical(env, key, NULL);
|
jbyte* keyBytes = (*env)->GetPrimitiveArrayCritical(env, key, NULL);
|
||||||
if (keyBytes == NULL) {
|
if (keyBytes == NULL) {
|
||||||
free(ctx);
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
throwException(env, "java/lang/OutOfMemoryError", "cipher get key");
|
throwException(env, "java/lang/OutOfMemoryError", "cipher get key");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_aes_init(&ctx->cipher);
|
int result = EVP_CipherInit(ctx, EVP_aes_128_cfb8(), (byte*) keyBytes, (byte*) keyBytes,
|
||||||
int ret = mbedtls_aes_setkey_enc(&ctx->cipher, (byte*) keyBytes, keyLen * 8);
|
encrypt);
|
||||||
if (ret != 0) {
|
// 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");
|
|
||||||
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);
|
(*env)->ReleasePrimitiveArrayCritical(env, key, keyBytes, 0);
|
||||||
|
|
||||||
|
if (result != 1) {
|
||||||
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
|
throwException(env, "java/security/GeneralSecurityException", "openssl initialize cipher");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return (jlong) ctx;
|
return (jlong) ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_free(JNIEnv *env,
|
Java_com_velocitypowered_natives_encryption_OpenSslCipherImpl_free(JNIEnv *env,
|
||||||
jobject obj,
|
jobject obj,
|
||||||
jlong ptr)
|
jlong ptr)
|
||||||
{
|
{
|
||||||
velocity_cipher_context *ctx = (velocity_cipher_context*) ptr;
|
EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *) ptr);
|
||||||
mbedtls_aes_free(&ctx->cipher);
|
|
||||||
free(ctx->key);
|
|
||||||
free(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_process(JNIEnv *env,
|
Java_com_velocitypowered_natives_encryption_OpenSslCipherImpl_process(JNIEnv *env,
|
||||||
jobject obj,
|
jobject obj,
|
||||||
jlong ptr,
|
jlong ptr,
|
||||||
jlong source,
|
jlong source,
|
||||||
jint len,
|
jint len,
|
||||||
jlong dest,
|
jlong dest)
|
||||||
jboolean encrypt)
|
|
||||||
{
|
{
|
||||||
velocity_cipher_context *ctx = (velocity_cipher_context*) ptr;
|
EVP_CipherUpdate((EVP_CIPHER_CTX*) ptr, (byte*) dest, &len, (byte*) source, len);
|
||||||
mbedtls_aes_crypt_cfb8(&ctx->cipher, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, len, ctx->key,
|
|
||||||
(byte*) source, (byte*) dest);
|
|
||||||
}
|
}
|
@ -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.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.natives.util.BufferPreference;
|
import com.velocitypowered.natives.util.BufferPreference;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.ShortBufferException;
|
|
||||||
|
|
||||||
public class NativeVelocityCipher implements VelocityCipher {
|
public class NativeVelocityCipher implements VelocityCipher {
|
||||||
|
|
||||||
@ -21,15 +19,13 @@ public class NativeVelocityCipher implements VelocityCipher {
|
|||||||
return new NativeVelocityCipher(false, key);
|
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 long ctx;
|
||||||
private final boolean encrypt;
|
|
||||||
private boolean disposed = false;
|
private boolean disposed = false;
|
||||||
|
|
||||||
private NativeVelocityCipher(boolean encrypt, SecretKey key) throws GeneralSecurityException {
|
private NativeVelocityCipher(boolean encrypt, SecretKey key) throws GeneralSecurityException {
|
||||||
this.encrypt = encrypt;
|
this.ctx = impl.init(key.getEncoded(), encrypt);
|
||||||
this.ctx = impl.init(key.getEncoded());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -40,7 +36,7 @@ public class NativeVelocityCipher implements VelocityCipher {
|
|||||||
long base = source.memoryAddress() + source.readerIndex();
|
long base = source.memoryAddress() + source.readerIndex();
|
||||||
int len = source.readableBytes();
|
int len = source.readableBytes();
|
||||||
|
|
||||||
impl.process(ctx, base, len, base, encrypt);
|
impl.process(ctx, base, len, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
||||||
|
}
|
@ -79,12 +79,18 @@ public class Natives {
|
|||||||
|
|
||||||
public static final NativeCodeLoader<VelocityCipherFactory> cipher = new NativeCodeLoader<>(
|
public static final NativeCodeLoader<VelocityCipherFactory> cipher = new NativeCodeLoader<>(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64,
|
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64,
|
||||||
copyAndLoadNative("/linux_x86_64/velocity-cipher.so"),
|
copyAndLoadNative("/linux_x86_64/velocity-cipher.so"), // Any local version
|
||||||
"mbed TLS (Linux x86_64)", NativeVelocityCipher.FACTORY),
|
"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,
|
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64,
|
||||||
copyAndLoadNative("/linux_aarch64/velocity-cipher.so"),
|
copyAndLoadNative("/linux_aarch64/velocity-cipher.so"),
|
||||||
"mbed TLS (Linux aarch64)", NativeVelocityCipher.FACTORY),
|
"OpenSSL (Linux aarch64)", NativeVelocityCipher.FACTORY),
|
||||||
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {
|
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {
|
||||||
}, "Java", JavaVelocityCipher.FACTORY)
|
}, "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
|
@Test
|
||||||
@Disabled
|
|
||||||
void nativeIntegrityCheck() throws GeneralSecurityException {
|
void nativeIntegrityCheck() throws GeneralSecurityException {
|
||||||
VelocityCipherFactory factory = Natives.cipher.get();
|
VelocityCipherFactory factory = Natives.cipher.get();
|
||||||
if (factory == JavaVelocityCipher.FACTORY) {
|
if (factory == JavaVelocityCipher.FACTORY) {
|
||||||
@ -39,11 +38,6 @@ class VelocityCipherTest {
|
|||||||
check(factory, Unpooled::directBuffer);
|
check(factory, Unpooled::directBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void javaIntegrityCheckDirect() throws GeneralSecurityException {
|
|
||||||
check(JavaVelocityCipher.FACTORY, Unpooled::directBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void javaIntegrityCheckHeap() throws GeneralSecurityException {
|
void javaIntegrityCheckHeap() throws GeneralSecurityException {
|
||||||
check(JavaVelocityCipher.FACTORY, Unpooled::buffer);
|
check(JavaVelocityCipher.FACTORY, Unpooled::buffer);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren