13
0
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:
Andrew Steinborn 2020-06-22 20:14:46 -04:00
Ursprung bd0455caa0
Commit 1bb84f81df
11 geänderte Dateien mit 50 neuen und 79 gelöschten Zeilen

1
.gitignore vendored
Datei anzeigen

@ -91,3 +91,4 @@ native/mbedtls
native/zlib-ng
native/zlib-cf
native/libdeflate
native/src/main/resources/linux_x86_64/velocity-cipher.so

Datei anzeigen

@ -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

Datei anzeigen

@ -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) {
(*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);
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);
if (result != 1) {
EVP_CIPHER_CTX_free(ctx);
throwException(env, "java/security/GeneralSecurityException", "openssl initialize cipher");
return 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);
}

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -79,12 +79,18 @@ 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),
new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64,
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äre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Datei anzeigen

@ -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);