Native cryptography support using mbed TLS
This commit is contained in:
81
native/src/main/c/jni_cipher.c
Normal file
81
native/src/main/c/jni_cipher.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mbedtls/aes.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,
|
||||
jobject obj,
|
||||
jbyteArray key)
|
||||
{
|
||||
velocity_cipher_context *ctx = malloc(sizeof(velocity_cipher_context));
|
||||
if (ctx == NULL) {
|
||||
throwException(env, "java/lang/OutOfMemoryError", "cipher allocate context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
jsize keyLen = (*env)->GetArrayLength(env, key);
|
||||
jbyte* keyBytes = (*env)->GetPrimitiveArrayCritical(env, key, NULL);
|
||||
if (keyBytes == NULL) {
|
||||
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);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, key, keyBytes, 0);
|
||||
return (jlong) ctx;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_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);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_velocitypowered_natives_encryption_MbedtlsAesImpl_process(JNIEnv *env,
|
||||
jobject obj,
|
||||
jlong ptr,
|
||||
jlong source,
|
||||
jint len,
|
||||
jlong dest,
|
||||
jboolean encrypt)
|
||||
{
|
||||
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);
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.velocitypowered.natives.encryption;
|
||||
|
||||
public class MbedtlsAesImpl {
|
||||
native long init(byte[] key);
|
||||
|
||||
native void process(long ctx, long sourceAddress, int sourceLength, long destinationAddress, boolean encrypt);
|
||||
|
||||
native void free(long ptr);
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package com.velocitypowered.natives.encryption;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
public class NativeVelocityCipher implements VelocityCipher {
|
||||
public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() {
|
||||
@Override
|
||||
public VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException {
|
||||
return new NativeVelocityCipher(true, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityCipher forDecryption(SecretKey key) throws GeneralSecurityException {
|
||||
return new NativeVelocityCipher(false, key);
|
||||
}
|
||||
};
|
||||
private static final MbedtlsAesImpl impl = new MbedtlsAesImpl();
|
||||
|
||||
private final long ctx;
|
||||
private final boolean encrypt;
|
||||
private boolean disposed = false;
|
||||
|
||||
private NativeVelocityCipher(boolean encrypt, SecretKey key) {
|
||||
this.encrypt = encrypt;
|
||||
this.ctx = impl.init(key.getEncoded());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ByteBuf source, ByteBuf destination) throws ShortBufferException {
|
||||
source.memoryAddress();
|
||||
destination.memoryAddress();
|
||||
|
||||
// The exact amount we read in is also the amount we write out.
|
||||
int len = source.readableBytes();
|
||||
destination.ensureWritable(len);
|
||||
|
||||
impl.process(ctx, source.memoryAddress() + source.readerIndex(), len,
|
||||
destination.memoryAddress() + destination.writerIndex(), encrypt);
|
||||
|
||||
source.skipBytes(len);
|
||||
destination.writerIndex(destination.writerIndex() + len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (!disposed) {
|
||||
impl.free(ctx);
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
@@ -6,6 +6,7 @@ import com.velocitypowered.natives.compression.NativeVelocityCompressor;
|
||||
import com.velocitypowered.natives.compression.VelocityCompressor;
|
||||
import com.velocitypowered.natives.compression.VelocityCompressorFactory;
|
||||
import com.velocitypowered.natives.encryption.JavaVelocityCipher;
|
||||
import com.velocitypowered.natives.encryption.NativeVelocityCipher;
|
||||
import com.velocitypowered.natives.encryption.VelocityCipherFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -51,6 +52,12 @@ public class Natives {
|
||||
|
||||
public static final NativeCodeLoader<VelocityCipherFactory> cipher = new NativeCodeLoader<>(
|
||||
ImmutableList.of(
|
||||
/*new NativeCodeLoader.Variant<>(NativeCodeLoader.MACOS,
|
||||
copyAndLoadNative("/macosx/velocity-cipher.dylib"), "mbed TLS cipher (macOS)",
|
||||
NativeVelocityCipher.FACTORY),
|
||||
new NativeCodeLoader.Variant<>(NativeCodeLoader.LINUX,
|
||||
copyAndLoadNative("/linux_x64/velocity-cipher.so"), "mbed TLS cipher (Linux amd64)",
|
||||
NativeVelocityCipher.FACTORY),*/
|
||||
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {}, "Java cipher", JavaVelocityCipher.FACTORY)
|
||||
)
|
||||
);
|
||||
|
Reference in New Issue
Block a user