diff --git a/transform_aes.c b/transform_aes.c index af03701..d8e1831 100644 --- a/transform_aes.c +++ b/transform_aes.c @@ -23,6 +23,8 @@ #include #include +#include +#include #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));