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.
This commit is contained in:
@@ -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);
|
||||
}
|
Reference in New Issue
Block a user