Native cryptography support using mbed TLS

This commit is contained in:
Andrew Steinborn
2018-08-04 23:46:41 -04:00
parent 06a6493605
commit 8aa1fe524e
11 changed files with 252 additions and 4 deletions

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

View File

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

View File

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

View File

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