made use of openssl's evp interface to achieve better hardware acceleration for AESed payload

This commit is contained in:
Logan007 2020-03-20 16:24:51 +01:00
parent 01f7825fd7
commit 8649de7a16

View File

@ -23,6 +23,8 @@
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#define N2N_AES_TRANSFORM_VERSION 1 /* version of the transform encoding */
#define N2N_AES_IVEC_SIZE (AES_BLOCK_SIZE)
@ -41,8 +43,8 @@
typedef unsigned char n2n_aes_ivec_t[N2N_AES_IVEC_SIZE];
typedef struct transop_aes {
AES_KEY enc_key; /* tx key */
AES_KEY dec_key; /* tx key */
const EVP_CIPHER *cipher; /* cipher to use: e.g. EVP_aes_128_cbc */
uint8_t key[32]; /* the pure key data for payload encryption & decryption */
AES_KEY iv_enc_key; /* key used to encrypt the IV */
uint8_t iv_pad_val[TRANSOP_AES_IV_PADDING_SIZE]; /* key used to pad the random IV seed to full block size */
} transop_aes_t;
@ -56,6 +58,20 @@ static int transop_deinit_aes(n2n_trans_op_t *arg) {
return 0;
}
/* get any erorr message out of openssl
taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling */
char *openssl_err_as_string (void) {
BIO *bio = BIO_new (BIO_s_mem ());
ERR_print_errors (bio);
char *buf = NULL;
size_t len = BIO_get_mem_data (bio, &buf);
char *ret = (char *) calloc (1, 1 + len);
if (ret)
memcpy (ret, buf, len);
BIO_free (bio);
return ret;
}
static void set_aes_cbc_iv(transop_aes_t *priv, n2n_aes_ivec_t ivec, uint64_t iv_seed) {
uint8_t iv_full[N2N_AES_IVEC_SIZE];
@ -129,10 +145,27 @@ static int transop_encode_aes( n2n_trans_op_t * arg,
set_aes_cbc_iv(priv, enc_ivec, iv_seed);
AES_cbc_encrypt( assembly, /* source */
outbuf + TRANSOP_AES_PREAMBLE_SIZE, /* dest */
len2, /* enc size */
&(priv->enc_key), enc_ivec, AES_ENCRYPT);
EVP_CIPHER_CTX *ctx;
int evp_len;
int evp_ciphertext_len;
if ((ctx = EVP_CIPHER_CTX_new())) {
if (1 == EVP_EncryptInit_ex(ctx, priv->cipher, NULL, priv->key, enc_ivec)) {
if (1 == EVP_CIPHER_CTX_set_padding(ctx, 0)) {
if (1 == EVP_EncryptUpdate(ctx, outbuf + TRANSOP_AES_PREAMBLE_SIZE, &evp_len, assembly, len2)) {
evp_ciphertext_len = evp_len;
if (1 == EVP_EncryptFinal_ex(ctx, outbuf + TRANSOP_AES_PREAMBLE_SIZE + evp_len, &evp_len)) {
evp_ciphertext_len += evp_len;
} else
traceEvent(TRACE_ERROR, "encode_aes openssl final encryption: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "encode_aes openssl encrpytion: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "encode_aes openssl padding setup: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "encode_aes openssl init: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "encode_aes openssl context creation: %s\n", openssl_err_as_string());
EVP_CIPHER_CTX_free(ctx);
len2 += TRANSOP_AES_PREAMBLE_SIZE; /* size of data carried in UDP. */
} else
@ -180,11 +213,27 @@ static int transop_decode_aes( n2n_trans_op_t * arg,
set_aes_cbc_iv(priv, dec_ivec, iv_seed);
AES_cbc_encrypt( (inbuf + TRANSOP_AES_PREAMBLE_SIZE),
assembly, /* destination */
len,
&(priv->dec_key),
dec_ivec, AES_DECRYPT);
EVP_CIPHER_CTX *ctx;
int evp_len;
int evp_plaintext_len;
if ((ctx = EVP_CIPHER_CTX_new())) {
if (1 == EVP_DecryptInit_ex(ctx, priv->cipher, NULL, priv->key, dec_ivec)) {
if (1 == EVP_CIPHER_CTX_set_padding(ctx, 0)) {
if (1 == EVP_DecryptUpdate(ctx, assembly, &evp_len, inbuf + TRANSOP_AES_PREAMBLE_SIZE, len)) {
evp_plaintext_len = evp_len;
if (1 == EVP_DecryptFinal_ex(ctx, assembly + evp_len, &evp_len)) {
evp_plaintext_len += evp_len;
} else
traceEvent(TRACE_ERROR, "decode_aes openssl final encryption: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "decode_aes openssl encrpytion: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "decode_aes openssl padding setup: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "decode_aes openssl init: %s\n", openssl_err_as_string());
} else
traceEvent(TRACE_ERROR, "decode_aes openssl context creation: %s\n", openssl_err_as_string());
EVP_CIPHER_CTX_free(ctx);
/* last byte is how much was padding: max value should be
* AES_BLOCKSIZE-1 */
@ -223,8 +272,7 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si
size_t key_mat_buf_length;
/* Clear out any old possibly longer key matter. */
memset( &(priv->enc_key), 0, sizeof(priv->enc_key) );
memset( &(priv->dec_key), 0, sizeof(priv->dec_key) );
memset( &(priv->key), 0, sizeof(priv->key) );
memset( &(priv->iv_enc_key), 0, sizeof(priv->iv_enc_key) );
memset( &(priv->iv_pad_val), 0, sizeof(priv->iv_pad_val) );
@ -245,12 +293,14 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si
if (key_size >= 65)
{
priv->cipher = EVP_aes_256_cbc();
aes_key_size_bytes = AES256_KEY_BYTES;
SHA512(key, key_size, key_mat_buf);
key_mat_buf_length = SHA512_DIGEST_LENGTH;
}
else if (key_size >= 44)
{
priv->cipher = EVP_aes_192_cbc();
aes_key_size_bytes = AES192_KEY_BYTES;
SHA384(key, key_size, key_mat_buf);
/* append a hash of the first hash to create enough material for IV padding */
@ -259,6 +309,7 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si
}
else
{
priv->cipher = EVP_aes_128_cbc();
aes_key_size_bytes = AES128_KEY_BYTES;
SHA256(key, key_size, key_mat_buf);
/* append a hash of the first hash to create enough material for IV padding */
@ -275,10 +326,9 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si
return(1);
}
/* setup of enc_key/dec_key, used for the CBC encryption */
/* setup of key, used for the CBC encryption */
aes_key_size_bits = 8 * aes_key_size_bytes;
AES_set_encrypt_key(key_mat_buf, aes_key_size_bits, &(priv->enc_key));
AES_set_decrypt_key(key_mat_buf, aes_key_size_bits, &(priv->dec_key));
memcpy (priv->key, key_mat_buf, aes_key_size_bytes);
/* setup of iv_enc_key (AES128 key) and iv_pad_val, used for generating the CBC IV */
AES_set_encrypt_key(key_mat_buf + aes_key_size_bytes, TRANSOP_AES_IV_KEY_BYTES * 8, &(priv->iv_enc_key));