From 1cc4996ef32f2d02ebc8b26822007cb282d5d831 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 24 Apr 2020 08:21:12 +0200 Subject: [PATCH] Added comparibility with OpenSSL 1.0 --- autogen.sh | 3 +- configure.seed | 10 ++-- transform_aes.c | 138 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 106 insertions(+), 45 deletions(-) diff --git a/autogen.sh b/autogen.sh index 8036442..3783341 100755 --- a/autogen.sh +++ b/autogen.sh @@ -18,5 +18,4 @@ rm -f config.h config.h.in *~ Makefile configure #* echo "Wait please..." autoreconf -if -echo "" -echo "Now run ./configure" +./configure diff --git a/configure.seed b/configure.seed index 044dd85..d1f0004 100644 --- a/configure.seed +++ b/configure.seed @@ -23,13 +23,17 @@ else N2N_LIBS=-lcrypto fi +OLD_CFLAGS="${CFLAGS}" +OLD_LDFLAGS="${LDFLAGS}" + CFLAGS="${CFLAGS} -I/usr/local/opt/openssl@1.1/include" LDFLAGS="${LDFLAGS} -L/usr/local/opt/openssl@1.1/lib/" AC_CHECK_LIB([crypto], [EVP_CIPHER_CTX_reset]) if test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_reset" != xyes; then - echo "" - echo "You do not seem to use OpenSSL 1.1 or better. Please upgrade" - echo "" + CFLAGS="${OLD_CFLAGS}" + LDFLAGS="${OLD_LDFLAGS}" +else + AC_DEFINE([HAVE_OPENSSL_1_1], [], [OpenSSL 1.1 is present]) fi AC_CHECK_LIB([pcap], [pcap_open_live], pcap=true) diff --git a/transform_aes.c b/transform_aes.c index 2c35056..bbfb4f0 100644 --- a/transform_aes.c +++ b/transform_aes.c @@ -43,19 +43,28 @@ typedef unsigned char n2n_aes_ivec_t[N2N_AES_IVEC_SIZE]; typedef struct transop_aes { - EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* encryption context */ - EVP_CIPHER_CTX *dec_ctx; /* openssl's reusable evp_* decryption context */ - 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 */ +#ifdef OPENSSL_1_1 + EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* encryption context */ + EVP_CIPHER_CTX *dec_ctx; /* openssl's reusable evp_* decryption context */ + 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 */ +#else + AES_KEY enc_key; /* tx key */ + AES_KEY dec_key; /* tx key */ +#endif 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; +/* ****************************************************** */ + static int transop_deinit_aes(n2n_trans_op_t *arg) { transop_aes_t *priv = (transop_aes_t *)arg->priv; +#ifdef OPENSSL_1_1 EVP_CIPHER_CTX_free(priv->enc_ctx); EVP_CIPHER_CTX_free(priv->dec_ctx); +#endif if(priv) free(priv); @@ -63,6 +72,9 @@ static int transop_deinit_aes(n2n_trans_op_t *arg) { return 0; } +/* ****************************************************** */ + +#ifdef OPENSSL_1_1 /* get any erorr message out of openssl taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling */ char *openssl_err_as_string (void) { @@ -71,11 +83,14 @@ char *openssl_err_as_string (void) { char *buf = NULL; size_t len = BIO_get_mem_data (bio, &buf); char *ret = (char *) calloc (1, 1 + len); - if (ret) + if(ret) memcpy (ret, buf, len); BIO_free (bio); return ret; } +#endif + +/* ****************************************************** */ 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]; @@ -93,6 +108,8 @@ static void set_aes_cbc_iv(transop_aes_t *priv, n2n_aes_ivec_t ivec, uint64_t iv AES_ecb_encrypt(iv_full, ivec, &priv->iv_enc_key, AES_ENCRYPT); } +/* ****************************************************** */ + /** The aes packet format consists of: * * - a 8-bit aes encoding version in clear text @@ -107,14 +124,13 @@ static int transop_encode_aes( n2n_trans_op_t * arg, size_t out_len, const uint8_t * inbuf, size_t in_len, - const uint8_t * peer_mac) -{ + const uint8_t * peer_mac) { int len2=-1; transop_aes_t * priv = (transop_aes_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE] = {0}; - if ( in_len <= N2N_PKT_BUF_SIZE) { - if ( (in_len + TRANSOP_AES_PREAMBLE_SIZE) <= out_len) { + if(in_len <= N2N_PKT_BUF_SIZE) { + if((in_len + TRANSOP_AES_PREAMBLE_SIZE) <= out_len) { int len=-1; size_t idx=0; uint64_t iv_seed = 0; @@ -150,17 +166,20 @@ static int transop_encode_aes( n2n_trans_op_t * arg, set_aes_cbc_iv(priv, enc_ivec, iv_seed); +#ifdef OPENSSL_1_1 EVP_CIPHER_CTX *ctx = priv->enc_ctx; int evp_len; int evp_ciphertext_len; - 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)) { + + 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)) { + if(1 == EVP_EncryptFinal_ex(ctx, outbuf + TRANSOP_AES_PREAMBLE_SIZE + evp_len, &evp_len)) { evp_ciphertext_len += evp_len; - if ( evp_ciphertext_len != len2) - traceEvent (TRACE_ERROR, "encode_aes openssl encryption: encrypted %u bytes where %u were expected.\n", + + if(evp_ciphertext_len != len2) + traceEvent(TRACE_ERROR, "encode_aes openssl encryption: encrypted %u bytes where %u were expected.\n", evp_ciphertext_len, len2); } else traceEvent(TRACE_ERROR, "encode_aes openssl final encryption: %s\n", openssl_err_as_string()); @@ -170,7 +189,14 @@ static int transop_encode_aes( n2n_trans_op_t * arg, 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()); + EVP_CIPHER_CTX_reset(ctx); +#else + AES_cbc_encrypt( assembly, /* source */ + outbuf + TRANSOP_AES_PREAMBLE_SIZE, /* dest */ + len2, /* enc size */ + &(priv->enc_key), enc_ivec, AES_ENCRYPT); +#endif len2 += TRANSOP_AES_PREAMBLE_SIZE; /* size of data carried in UDP. */ } else @@ -181,6 +207,8 @@ static int transop_encode_aes( n2n_trans_op_t * arg, return len2; } +/* ****************************************************** */ + /* See transop_encode_aes for packet format */ static int transop_decode_aes( n2n_trans_op_t * arg, uint8_t * outbuf, @@ -192,7 +220,7 @@ static int transop_decode_aes( n2n_trans_op_t * arg, transop_aes_t * priv = (transop_aes_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE]; - if ( ( (in_len - TRANSOP_AES_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in assembly */ + if(( (in_len - TRANSOP_AES_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in assembly */ && (in_len >= TRANSOP_AES_PREAMBLE_SIZE) /* Has at least version, iv seed */ ) { @@ -204,7 +232,7 @@ static int transop_decode_aes( n2n_trans_op_t * arg, /* Get the encoding version to make sure it is supported */ decode_uint8( &aes_enc_ver, inbuf, &rem, &idx ); - if ( N2N_AES_TRANSFORM_VERSION == aes_enc_ver) { + if(N2N_AES_TRANSFORM_VERSION == aes_enc_ver) { /* Get the IV seed */ decode_buf((uint8_t *)&iv_seed, TRANSOP_AES_IV_SEED_SIZE, inbuf, &rem, &idx); @@ -212,23 +240,26 @@ static int transop_decode_aes( n2n_trans_op_t * arg, len = (in_len - TRANSOP_AES_PREAMBLE_SIZE); - if ( 0 == (len % AES_BLOCK_SIZE)) { + if(0 == (len % AES_BLOCK_SIZE)) { uint8_t padding; n2n_aes_ivec_t dec_ivec = {0}; set_aes_cbc_iv(priv, dec_ivec, iv_seed); +#ifdef OPENSSL_1_1 EVP_CIPHER_CTX *ctx = priv->dec_ctx; int evp_len; int evp_plaintext_len; - 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)) { + + 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)) { + if(1 == EVP_DecryptFinal_ex(ctx, assembly + evp_len, &evp_len)) { evp_plaintext_len += evp_len; - if ( evp_plaintext_len != len) - traceEvent (TRACE_ERROR, "decode_aes openssl decryption: decrypted %u bytes where %u were expected.\n", + + if(evp_plaintext_len != len) + traceEvent(TRACE_ERROR, "decode_aes openssl decryption: decrypted %u bytes where %u were expected.\n", evp_plaintext_len, len); } else traceEvent(TRACE_ERROR, "decode_aes openssl final decryption: %s\n", openssl_err_as_string()); @@ -236,16 +267,23 @@ static int transop_decode_aes( n2n_trans_op_t * arg, traceEvent(TRACE_ERROR, "decode_aes openssl decrpytion: %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()); - EVP_CIPHER_CTX_reset(ctx); + EVP_CIPHER_CTX_reset(ctx); +#else + AES_cbc_encrypt( (inbuf + TRANSOP_AES_PREAMBLE_SIZE), + assembly, /* destination */ + len, + &(priv->dec_key), + dec_ivec, AES_DECRYPT); +#endif /* last byte is how much was padding: max value should be * AES_BLOCKSIZE-1 */ padding = assembly[ len-1 ] & 0xff; - if ( len >= padding) - { + if(len >= padding) { /* strictly speaking for this to be an ethernet packet * it is going to need to be even bigger; but this is * enough to prevent segfaults. */ @@ -269,6 +307,8 @@ static int transop_decode_aes( n2n_trans_op_t * arg, return len; } +/* ****************************************************** */ + static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_size) { size_t aes_key_size_bytes; size_t aes_key_size_bits; @@ -277,7 +317,12 @@ 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. */ +#ifdef OPENSSL_1_1 memset( &(priv->key), 0, sizeof(priv->key) ); +#else + memset( &(priv->enc_key), 0, sizeof(priv->enc_key) ); + memset( &(priv->dec_key), 0, sizeof(priv->dec_key) ); +#endif memset( &(priv->iv_enc_key), 0, sizeof(priv->iv_enc_key) ); memset( &(priv->iv_pad_val), 0, sizeof(priv->iv_pad_val) ); @@ -296,25 +341,26 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si * actual "filling level" of the buffer */ - if (key_size >= 65) - { + if(key_size >= 65) { +#ifdef OPENSSL_1_1 priv->cipher = EVP_aes_256_cbc(); +#endif 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) - { + } else if(key_size >= 44) { +#ifdef OPENSSL_1_1 priv->cipher = EVP_aes_192_cbc(); +#endif 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 */ SHA256(key_mat_buf, SHA384_DIGEST_LENGTH, key_mat_buf + SHA384_DIGEST_LENGTH); key_mat_buf_length = SHA384_DIGEST_LENGTH + SHA256_DIGEST_LENGTH; - } - else - { + } else { +#ifdef OPENSSL_1_1 priv->cipher = EVP_aes_128_cbc(); +#endif 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 */ @@ -323,8 +369,7 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si } /* is there enough material available? */ - if (key_mat_buf_length < (aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES + TRANSOP_AES_IV_PADDING_SIZE)) - { + if(key_mat_buf_length < (aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES + TRANSOP_AES_IV_PADDING_SIZE)) { /* this should never happen */ traceEvent( TRACE_ERROR, "AES missing %u bits hashed key material\n", (aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES + TRANSOP_AES_IV_PADDING_SIZE - key_mat_buf_length) * 8); @@ -333,7 +378,13 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si /* setup of key, used for the CBC encryption */ aes_key_size_bits = 8 * aes_key_size_bytes; + +#ifdef OPENSSL_1_1 memcpy (priv->key, key_mat_buf, aes_key_size_bytes); +#else + 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)); +#endif /* 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)); @@ -345,7 +396,11 @@ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_si return(0); } -static void transop_tick_aes(n2n_trans_op_t * arg, time_t now) {} +/* ****************************************************** */ + +static void transop_tick_aes(n2n_trans_op_t * arg, time_t now) { ; } + +/* ****************************************************** */ /* AES initialization function */ int n2n_transop_aes_cbc_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { @@ -368,15 +423,18 @@ int n2n_transop_aes_cbc_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { } ttt->priv = priv; +#ifdef OPENSSL_1_1 /* Setup openssl's reusable evp_* contexts for encryption and decryption*/ - if (!(priv->enc_ctx = EVP_CIPHER_CTX_new())) { + if(!(priv->enc_ctx = EVP_CIPHER_CTX_new())) { traceEvent(TRACE_ERROR, "openssl's evp_* encryption context creation: %s\n", openssl_err_as_string()); return(-1); } - if (!(priv->dec_ctx = EVP_CIPHER_CTX_new())) { + + if(!(priv->dec_ctx = EVP_CIPHER_CTX_new())) { traceEvent(TRACE_ERROR, "openssl's evp_* decryption context creation: %s\n", openssl_err_as_string()); return(-1); } +#endif /* Setup the cipher and key */ return(setup_aes_key(priv, encrypt_key, encrypt_key_len));