From 97c89481135ec01f1c20c0651d789bdce20ed56c Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 24 Apr 2020 00:36:32 +0200 Subject: [PATCH] MacOS fixes --- Makefile.in | 14 +- configure.seed | 13 +- tools/Makefile.in | 7 +- transform_aes.c | 492 +++++++++++++++++++++++----------------------- 4 files changed, 269 insertions(+), 257 deletions(-) diff --git a/Makefile.in b/Makefile.in index 5dccec8..14f5599 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,10 +16,12 @@ PLATOPTS_SPARC64=-mcpu=ultrasparc -pipe -fomit-frame-pointer -ffast-math -finlin N2N_OBJS_OPT= LIBS_EDGE_OPT=@N2N_LIBS@ +CFLAGS=@CFLAGS@ +LDFLAGS=@LDFLAGS@ OPENSSL_CFLAGS=$(shell pkg-config openssl; echo $$?) ifeq ($(OPENSSL_CFLAGS), 0) - CFLAGS+=$(shell pkg-config --cflags-only-I openssl) + CFLAGS+=$(shell pkg-config --cflags-only-I openssl) endif CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) $(OPTIONS) $(PLATOPTS) @@ -75,19 +77,19 @@ tools: $(N2N_LIB) $(MAKE) -C $@ edge: edge.c $(N2N_LIB) n2n_wire.h n2n.h Makefile - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_EDGE) -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ supernode: sn.c $(N2N_LIB) n2n.h Makefile - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_SN) -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_SN) -o $@ example_edge_embed_quick_edge_init: example_edge_embed_quick_edge_init.c $(N2N_LIB) n2n.h - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_EDGE) -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ example_sn_embed: example_sn_embed.c $(N2N_LIB) n2n.h - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_EDGE) -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ example_edge_embed: example_edge_embed.c $(N2N_LIB) n2n.h - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_EDGE) -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ .c.o: n2n.h n2n_transforms.h n2n_wire.h twofish.h Makefile $(CC) $(CFLAGS) -c $< -o $@ diff --git a/configure.seed b/configure.seed index 0f8b596..044dd85 100644 --- a/configure.seed +++ b/configure.seed @@ -16,7 +16,6 @@ fi AC_CHECK_LIB([crypto], [AES_cbc_encrypt]) N2N_LIBS= - if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != xyes; then AC_MSG_RESULT(Building n2n without AES support) else @@ -24,6 +23,15 @@ else N2N_LIBS=-lcrypto fi +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 "" +fi + AC_CHECK_LIB([pcap], [pcap_open_live], pcap=true) if test x$pcap != x; then @@ -64,6 +72,8 @@ fi DATE=`date +"%Y-%m-%d"` +AC_SUBST(CFLAGS) +AC_SUBST(LDFLAGS) AC_SUBST(N2N_MAJOR) AC_SUBST(N2N_MINOR) AC_SUBST(N2N_PATCH) @@ -79,4 +89,3 @@ AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(tools/Makefile) AC_OUTPUT - diff --git a/tools/Makefile.in b/tools/Makefile.in index bcb3e02..3679f7a 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -17,9 +17,10 @@ endif LIBS_EDGE_OPT=@N2N_LIBS@ LIBS_EDGE+=$(LIBS_EDGE_OPT) HEADERS=../n2n_wire.h ../n2n.h ../twofish.h ../n2n_transforms.h -CFLAGS+=-I.. +CFLAGS+=-I.. @CFLAGS@ LDFLAGS+=-L.. CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) +LDFLAGS=@LDFLAGS@ N2N_LIB=../libn2n.a @@ -30,10 +31,10 @@ TOOLS+=@ADDITIONAL_TOOLS@ all: $(TOOLS) n2n-benchmark: benchmark.c $(N2N_LIB) $(HEADERS) - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_EDGE) -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ n2n-decode: n2n_decode.c $(N2N_LIB) $(HEADERS) - $(CC) $(CFLAGS) $< $(N2N_LIB) $(LIBS_EDGE) -lpcap -o $@ + $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -lpcap -o $@ .c.o: $(HEADERS) ../Makefile Makefile $(CC) $(CFLAGS) -c $< -o $@ diff --git a/transform_aes.c b/transform_aes.c index a374408..2c35056 100644 --- a/transform_aes.c +++ b/transform_aes.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,54 +43,54 @@ 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 */ - 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 */ + 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 */ + 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; + transop_aes_t *priv = (transop_aes_t *)arg->priv; - EVP_CIPHER_CTX_free(priv->enc_ctx); - EVP_CIPHER_CTX_free(priv->dec_ctx); + EVP_CIPHER_CTX_free(priv->enc_ctx); + EVP_CIPHER_CTX_free(priv->dec_ctx); - if(priv) - free(priv); + if(priv) + free(priv); - return 0; + 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; + 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]; - - /* Extend the seed to full block size with padding value */ - memcpy(iv_full, priv->iv_pad_val, TRANSOP_AES_IV_PADDING_SIZE); - memcpy(iv_full + TRANSOP_AES_IV_PADDING_SIZE, &iv_seed, TRANSOP_AES_IV_SEED_SIZE); - - /* Encrypt the IV with secret key to make it unpredictable. - * As discussed in https://github.com/ntop/n2n/issues/72, it's important to - * have an unpredictable IV since the initial part of the packet plaintext - * can be easily reconstructed from plaintext headers and used by an attacker - * to perform differential analysis. - */ - AES_ecb_encrypt(iv_full, ivec, &priv->iv_enc_key, AES_ENCRYPT); + uint8_t iv_full[N2N_AES_IVEC_SIZE]; + + /* Extend the seed to full block size with padding value */ + memcpy(iv_full, priv->iv_pad_val, TRANSOP_AES_IV_PADDING_SIZE); + memcpy(iv_full + TRANSOP_AES_IV_PADDING_SIZE, &iv_seed, TRANSOP_AES_IV_SEED_SIZE); + + /* Encrypt the IV with secret key to make it unpredictable. + * As discussed in https://github.com/ntop/n2n/issues/72, it's important to + * have an unpredictable IV since the initial part of the packet plaintext + * can be easily reconstructed from plaintext headers and used by an attacker + * to perform differential analysis. + */ + AES_ecb_encrypt(iv_full, ivec, &priv->iv_enc_key, AES_ENCRYPT); } /** The aes packet format consists of: @@ -103,246 +103,246 @@ static void set_aes_cbc_iv(transop_aes_t *priv, n2n_aes_ivec_t ivec, uint64_t iv * |<---- encrypted ---->| */ static int transop_encode_aes( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len, - const uint8_t * peer_mac) + uint8_t * outbuf, + size_t out_len, + const uint8_t * inbuf, + size_t in_len, + 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) { - int len=-1; - size_t idx=0; - uint64_t iv_seed = 0; - uint8_t padding = 0; - n2n_aes_ivec_t enc_ivec = {0}; - - traceEvent(TRACE_DEBUG, "encode_aes %lu", in_len); - - /* Encode the aes format version. */ - encode_uint8( outbuf, &idx, N2N_AES_TRANSFORM_VERSION); - - /* Generate and encode the IV seed. - * Using two calls to rand() because RAND_MAX is usually < 64bit - * (e.g. linux) and sometimes < 32bit (e.g. Windows). - */ - iv_seed = ((((uint64_t)rand() & 0xFFFFFFFF)) << 32) | rand(); - encode_buf(outbuf, &idx, &iv_seed, TRANSOP_AES_IV_SEED_SIZE); - - /* Encrypt the assembly contents and write the ciphertext after the iv seed. */ - /* len is set to the length of the cipher plain text to be encrpyted - which is (in this case) identical to original packet lentgh */ - len = in_len; - - /* The assembly buffer is a source for encrypting data. - * The whole contents of assembly are encrypted. */ - memcpy( assembly, inbuf, in_len); - - /* Need at least one encrypted byte at the end for the padding. */ - len2 = ( (len / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; /* Round up to next whole AES adding at least one byte. */ - padding = (len2-len); - assembly[len2 - 1] = padding; - traceEvent(TRACE_DEBUG, "padding = %u, seed = %016llx", padding, iv_seed); - - set_aes_cbc_iv(priv, enc_ivec, iv_seed); - - 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)) { - 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; - 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()); - } 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()); + 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) { + int len=-1; + size_t idx=0; + uint64_t iv_seed = 0; + uint8_t padding = 0; + n2n_aes_ivec_t enc_ivec = {0}; + + traceEvent(TRACE_DEBUG, "encode_aes %lu", in_len); + + /* Encode the aes format version. */ + encode_uint8( outbuf, &idx, N2N_AES_TRANSFORM_VERSION); + + /* Generate and encode the IV seed. + * Using two calls to rand() because RAND_MAX is usually < 64bit + * (e.g. linux) and sometimes < 32bit (e.g. Windows). + */ + iv_seed = ((((uint64_t)rand() & 0xFFFFFFFF)) << 32) | rand(); + encode_buf(outbuf, &idx, &iv_seed, TRANSOP_AES_IV_SEED_SIZE); + + /* Encrypt the assembly contents and write the ciphertext after the iv seed. */ + /* len is set to the length of the cipher plain text to be encrpyted + which is (in this case) identical to original packet lentgh */ + len = in_len; + + /* The assembly buffer is a source for encrypting data. + * The whole contents of assembly are encrypted. */ + memcpy( assembly, inbuf, in_len); + + /* Need at least one encrypted byte at the end for the padding. */ + len2 = ( (len / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; /* Round up to next whole AES adding at least one byte. */ + padding = (len2-len); + assembly[len2 - 1] = padding; + traceEvent(TRACE_DEBUG, "padding = %u, seed = %016llx", padding, iv_seed); + + set_aes_cbc_iv(priv, enc_ivec, iv_seed); + + 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)) { + 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; + 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 init: %s\n", openssl_err_as_string()); - EVP_CIPHER_CTX_reset(ctx); - - len2 += TRANSOP_AES_PREAMBLE_SIZE; /* size of data carried in UDP. */ - } else - traceEvent(TRACE_ERROR, "encode_aes outbuf too small."); + 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()); + EVP_CIPHER_CTX_reset(ctx); + + len2 += TRANSOP_AES_PREAMBLE_SIZE; /* size of data carried in UDP. */ } else - traceEvent(TRACE_ERROR, "encode_aes inbuf too big to encrypt."); + traceEvent(TRACE_ERROR, "encode_aes outbuf too small."); + } else + traceEvent(TRACE_ERROR, "encode_aes inbuf too big to encrypt."); - return len2; + return len2; } /* See transop_encode_aes for packet format */ static int transop_decode_aes( n2n_trans_op_t * arg, - uint8_t * outbuf, - size_t out_len, - const uint8_t * inbuf, - size_t in_len, - const uint8_t * peer_mac) { - int len=0; - 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 */ - && (in_len >= TRANSOP_AES_PREAMBLE_SIZE) /* Has at least version, iv seed */ + uint8_t * outbuf, + size_t out_len, + const uint8_t * inbuf, + size_t in_len, + const uint8_t * peer_mac) { + int len=0; + 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 */ + && (in_len >= TRANSOP_AES_PREAMBLE_SIZE) /* Has at least version, iv seed */ ) { - size_t rem=in_len; - size_t idx=0; - uint8_t aes_enc_ver=0; - uint64_t iv_seed=0; - - /* 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) { - /* Get the IV seed */ - decode_buf((uint8_t *)&iv_seed, TRANSOP_AES_IV_SEED_SIZE, inbuf, &rem, &idx); - - traceEvent(TRACE_DEBUG, "decode_aes %lu with seed %016llx", in_len, iv_seed); - - len = (in_len - TRANSOP_AES_PREAMBLE_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); - - 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)) { - evp_plaintext_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", - evp_plaintext_len, len); - } else - traceEvent(TRACE_ERROR, "decode_aes openssl final decryption: %s\n", openssl_err_as_string()); - } else - 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()); + size_t rem=in_len; + size_t idx=0; + uint8_t aes_enc_ver=0; + uint64_t iv_seed=0; + + /* 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) { + /* Get the IV seed */ + decode_buf((uint8_t *)&iv_seed, TRANSOP_AES_IV_SEED_SIZE, inbuf, &rem, &idx); + + traceEvent(TRACE_DEBUG, "decode_aes %lu with seed %016llx", in_len, iv_seed); + + len = (in_len - TRANSOP_AES_PREAMBLE_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); + + 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)) { + evp_plaintext_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", + evp_plaintext_len, len); } else - traceEvent(TRACE_ERROR, "decode_aes openssl init: %s\n", openssl_err_as_string()); - EVP_CIPHER_CTX_reset(ctx); - - /* last byte is how much was padding: max value should be - * AES_BLOCKSIZE-1 */ - padding = assembly[ len-1 ] & 0xff; - - 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. */ - traceEvent(TRACE_DEBUG, "padding = %u", padding); - len -= padding; - - memcpy( outbuf, - assembly, - len); - } else - traceEvent(TRACE_WARNING, "UDP payload decryption failed."); - } else { - traceEvent(TRACE_WARNING, "Encrypted length %d is not a multiple of AES_BLOCK_SIZE (%d)", len, AES_BLOCK_SIZE); - len = 0; - } - } else - traceEvent(TRACE_ERROR, "decode_aes unsupported aes version %u.", aes_enc_ver); + traceEvent(TRACE_ERROR, "decode_aes openssl final decryption: %s\n", openssl_err_as_string()); + } else + 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); + + /* last byte is how much was padding: max value should be + * AES_BLOCKSIZE-1 */ + padding = assembly[ len-1 ] & 0xff; + + 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. */ + traceEvent(TRACE_DEBUG, "padding = %u", padding); + len -= padding; + + memcpy( outbuf, + assembly, + len); + } else + traceEvent(TRACE_WARNING, "UDP payload decryption failed."); + } else { + traceEvent(TRACE_WARNING, "Encrypted length %d is not a multiple of AES_BLOCK_SIZE (%d)", len, AES_BLOCK_SIZE); + len = 0; + } + } else + traceEvent(TRACE_ERROR, "decode_aes unsupported aes version %u.", aes_enc_ver); } else - traceEvent(TRACE_ERROR, "decode_aes inbuf wrong size (%ul) to decrypt.", in_len); + traceEvent(TRACE_ERROR, "decode_aes inbuf wrong size (%ul) to decrypt.", in_len); - return len; + 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; - - uint8_t key_mat_buf[SHA512_DIGEST_LENGTH + SHA256_DIGEST_LENGTH]; - size_t key_mat_buf_length; - - /* Clear out any old possibly longer key matter. */ - 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) ); - - /* Let the user choose the degree of encryption: - * Long input keys will pick AES192 or AES256 with more robust but expensive encryption. - * - * The input key always gets hashed to make a more unpredictable use of the key space and - * also to derive some additional material (key for IV encrpytion, IV padding). - * - * The following scheme for key setup was discussed on github: - * https://github.com/ntop/n2n/issues/101 - */ - - /* create a working buffer of maximal occuring hashes size and generate - * the hashes for the aes key material, key_mat_buf_lengh indicates the - * actual "filling level" of the buffer - */ - - if (key_size >= 65) + size_t aes_key_size_bytes; + size_t aes_key_size_bits; + + uint8_t key_mat_buf[SHA512_DIGEST_LENGTH + SHA256_DIGEST_LENGTH]; + size_t key_mat_buf_length; + + /* Clear out any old possibly longer key matter. */ + 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) ); + + /* Let the user choose the degree of encryption: + * Long input keys will pick AES192 or AES256 with more robust but expensive encryption. + * + * The input key always gets hashed to make a more unpredictable use of the key space and + * also to derive some additional material (key for IV encrpytion, IV padding). + * + * The following scheme for key setup was discussed on github: + * https://github.com/ntop/n2n/issues/101 + */ + + /* create a working buffer of maximal occuring hashes size and generate + * the hashes for the aes key material, key_mat_buf_lengh indicates the + * actual "filling level" of the buffer + */ + + 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; + 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) + 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 */ - SHA256(key_mat_buf, SHA384_DIGEST_LENGTH, key_mat_buf + SHA384_DIGEST_LENGTH); - key_mat_buf_length = SHA384_DIGEST_LENGTH + SHA256_DIGEST_LENGTH; + 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 */ + 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 { - 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 */ - SHA256(key_mat_buf, SHA256_DIGEST_LENGTH, key_mat_buf + SHA256_DIGEST_LENGTH); - key_mat_buf_length = 2 * SHA256_DIGEST_LENGTH; + 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 */ + SHA256(key_mat_buf, SHA256_DIGEST_LENGTH, key_mat_buf + SHA256_DIGEST_LENGTH); + key_mat_buf_length = 2 * SHA256_DIGEST_LENGTH; } - /* is there enough material available? */ - if (key_mat_buf_length < (aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES + TRANSOP_AES_IV_PADDING_SIZE)) + /* is there enough material available? */ + 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); - return(1); + /* 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); + return(1); } - /* setup of key, used for the CBC encryption */ - aes_key_size_bits = 8 * aes_key_size_bytes; - memcpy (priv->key, key_mat_buf, aes_key_size_bytes); + /* setup of key, used for the CBC encryption */ + aes_key_size_bits = 8 * aes_key_size_bytes; + 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)); - memcpy(priv->iv_pad_val, key_mat_buf + aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES, TRANSOP_AES_IV_PADDING_SIZE); + /* 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)); + memcpy(priv->iv_pad_val, key_mat_buf + aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES, TRANSOP_AES_IV_PADDING_SIZE); - traceEvent(TRACE_DEBUG, "AES %u bits setup completed\n", - aes_key_size_bits); + traceEvent(TRACE_DEBUG, "AES %u bits setup completed\n", + aes_key_size_bits); - return(0); + return(0); } static void transop_tick_aes(n2n_trans_op_t * arg, time_t now) {}