Browse Source

MacOS fixes

pull/232/head
Luca Deri 5 years ago
parent
commit
97c8948113
  1. 14
      Makefile.in
  2. 13
      configure.seed
  3. 7
      tools/Makefile.in
  4. 492
      transform_aes.c

14
Makefile.in

@ -16,10 +16,12 @@ PLATOPTS_SPARC64=-mcpu=ultrasparc -pipe -fomit-frame-pointer -ffast-math -finlin
N2N_OBJS_OPT= N2N_OBJS_OPT=
LIBS_EDGE_OPT=@N2N_LIBS@ LIBS_EDGE_OPT=@N2N_LIBS@
CFLAGS=@CFLAGS@
LDFLAGS=@LDFLAGS@
OPENSSL_CFLAGS=$(shell pkg-config openssl; echo $$?) OPENSSL_CFLAGS=$(shell pkg-config openssl; echo $$?)
ifeq ($(OPENSSL_CFLAGS), 0) ifeq ($(OPENSSL_CFLAGS), 0)
CFLAGS+=$(shell pkg-config --cflags-only-I openssl) CFLAGS+=$(shell pkg-config --cflags-only-I openssl)
endif endif
CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) $(OPTIONS) $(PLATOPTS) CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) $(OPTIONS) $(PLATOPTS)
@ -75,19 +77,19 @@ tools: $(N2N_LIB)
$(MAKE) -C $@ $(MAKE) -C $@
edge: edge.c $(N2N_LIB) n2n_wire.h n2n.h Makefile 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 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 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 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 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 .c.o: n2n.h n2n_transforms.h n2n_wire.h twofish.h Makefile
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@

13
configure.seed

@ -16,7 +16,6 @@ fi
AC_CHECK_LIB([crypto], [AES_cbc_encrypt]) AC_CHECK_LIB([crypto], [AES_cbc_encrypt])
N2N_LIBS= N2N_LIBS=
if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != xyes; then if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != xyes; then
AC_MSG_RESULT(Building n2n without AES support) AC_MSG_RESULT(Building n2n without AES support)
else else
@ -24,6 +23,15 @@ else
N2N_LIBS=-lcrypto N2N_LIBS=-lcrypto
fi 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) AC_CHECK_LIB([pcap], [pcap_open_live], pcap=true)
if test x$pcap != x; then if test x$pcap != x; then
@ -64,6 +72,8 @@ fi
DATE=`date +"%Y-%m-%d"` DATE=`date +"%Y-%m-%d"`
AC_SUBST(CFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(N2N_MAJOR) AC_SUBST(N2N_MAJOR)
AC_SUBST(N2N_MINOR) AC_SUBST(N2N_MINOR)
AC_SUBST(N2N_PATCH) AC_SUBST(N2N_PATCH)
@ -79,4 +89,3 @@ AC_CONFIG_FILES(Makefile)
AC_CONFIG_FILES(tools/Makefile) AC_CONFIG_FILES(tools/Makefile)
AC_OUTPUT AC_OUTPUT

7
tools/Makefile.in

@ -17,9 +17,10 @@ endif
LIBS_EDGE_OPT=@N2N_LIBS@ LIBS_EDGE_OPT=@N2N_LIBS@
LIBS_EDGE+=$(LIBS_EDGE_OPT) LIBS_EDGE+=$(LIBS_EDGE_OPT)
HEADERS=../n2n_wire.h ../n2n.h ../twofish.h ../n2n_transforms.h HEADERS=../n2n_wire.h ../n2n.h ../twofish.h ../n2n_transforms.h
CFLAGS+=-I.. CFLAGS+=-I.. @CFLAGS@
LDFLAGS+=-L.. LDFLAGS+=-L..
CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN)
LDFLAGS=@LDFLAGS@
N2N_LIB=../libn2n.a N2N_LIB=../libn2n.a
@ -30,10 +31,10 @@ TOOLS+=@ADDITIONAL_TOOLS@
all: $(TOOLS) all: $(TOOLS)
n2n-benchmark: benchmark.c $(N2N_LIB) $(HEADERS) 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) 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 .c.o: $(HEADERS) ../Makefile Makefile
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@

492
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 * 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 * 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 unsigned char n2n_aes_ivec_t[N2N_AES_IVEC_SIZE];
typedef struct transop_aes { typedef struct transop_aes {
EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* encryption context */ EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* encryption context */
EVP_CIPHER_CTX *dec_ctx; /* openssl's reusable evp_* decryption 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 */ 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 */ uint8_t key[32]; /* the pure key data for payload encryption & decryption */
AES_KEY iv_enc_key; /* key used to encrypt the IV */ 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 */ 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; } transop_aes_t;
static int transop_deinit_aes(n2n_trans_op_t *arg) { 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->enc_ctx);
EVP_CIPHER_CTX_free(priv->dec_ctx); EVP_CIPHER_CTX_free(priv->dec_ctx);
if(priv) if(priv)
free(priv); free(priv);
return 0; return 0;
} }
/* get any erorr message out of openssl /* get any erorr message out of openssl
taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling */ taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling */
char *openssl_err_as_string (void) { char *openssl_err_as_string (void) {
BIO *bio = BIO_new (BIO_s_mem ()); BIO *bio = BIO_new (BIO_s_mem ());
ERR_print_errors (bio); ERR_print_errors (bio);
char *buf = NULL; char *buf = NULL;
size_t len = BIO_get_mem_data (bio, &buf); size_t len = BIO_get_mem_data (bio, &buf);
char *ret = (char *) calloc (1, 1 + len); char *ret = (char *) calloc (1, 1 + len);
if (ret) if (ret)
memcpy (ret, buf, len); memcpy (ret, buf, len);
BIO_free (bio); BIO_free (bio);
return ret; return ret;
} }
static void set_aes_cbc_iv(transop_aes_t *priv, n2n_aes_ivec_t ivec, uint64_t iv_seed) { 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]; uint8_t iv_full[N2N_AES_IVEC_SIZE];
/* Extend the seed to full block size with padding value */ /* 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, priv->iv_pad_val, TRANSOP_AES_IV_PADDING_SIZE);
memcpy(iv_full + TRANSOP_AES_IV_PADDING_SIZE, &iv_seed, TRANSOP_AES_IV_SEED_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. /* Encrypt the IV with secret key to make it unpredictable.
* As discussed in https://github.com/ntop/n2n/issues/72, it's important to * 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 * have an unpredictable IV since the initial part of the packet plaintext
* can be easily reconstructed from plaintext headers and used by an attacker * can be easily reconstructed from plaintext headers and used by an attacker
* to perform differential analysis. * to perform differential analysis.
*/ */
AES_ecb_encrypt(iv_full, ivec, &priv->iv_enc_key, AES_ENCRYPT); AES_ecb_encrypt(iv_full, ivec, &priv->iv_enc_key, AES_ENCRYPT);
} }
/** The aes packet format consists of: /** 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 ---->| * |<---- encrypted ---->|
*/ */
static int transop_encode_aes( n2n_trans_op_t * arg, static int transop_encode_aes( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len, size_t in_len,
const uint8_t * peer_mac) const uint8_t * peer_mac)
{ {
int len2=-1; int len2=-1;
transop_aes_t * priv = (transop_aes_t *)arg->priv; transop_aes_t * priv = (transop_aes_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE] = {0}; uint8_t assembly[N2N_PKT_BUF_SIZE] = {0};
if ( in_len <= N2N_PKT_BUF_SIZE) { if ( in_len <= N2N_PKT_BUF_SIZE) {
if ( (in_len + TRANSOP_AES_PREAMBLE_SIZE) <= out_len) { if ( (in_len + TRANSOP_AES_PREAMBLE_SIZE) <= out_len) {
int len=-1; int len=-1;
size_t idx=0; size_t idx=0;
uint64_t iv_seed = 0; uint64_t iv_seed = 0;
uint8_t padding = 0; uint8_t padding = 0;
n2n_aes_ivec_t enc_ivec = {0}; n2n_aes_ivec_t enc_ivec = {0};
traceEvent(TRACE_DEBUG, "encode_aes %lu", in_len); traceEvent(TRACE_DEBUG, "encode_aes %lu", in_len);
/* Encode the aes format version. */ /* Encode the aes format version. */
encode_uint8( outbuf, &idx, N2N_AES_TRANSFORM_VERSION); encode_uint8( outbuf, &idx, N2N_AES_TRANSFORM_VERSION);
/* Generate and encode the IV seed. /* Generate and encode the IV seed.
* Using two calls to rand() because RAND_MAX is usually < 64bit * Using two calls to rand() because RAND_MAX is usually < 64bit
* (e.g. linux) and sometimes < 32bit (e.g. Windows). * (e.g. linux) and sometimes < 32bit (e.g. Windows).
*/ */
iv_seed = ((((uint64_t)rand() & 0xFFFFFFFF)) << 32) | rand(); iv_seed = ((((uint64_t)rand() & 0xFFFFFFFF)) << 32) | rand();
encode_buf(outbuf, &idx, &iv_seed, TRANSOP_AES_IV_SEED_SIZE); encode_buf(outbuf, &idx, &iv_seed, TRANSOP_AES_IV_SEED_SIZE);
/* Encrypt the assembly contents and write the ciphertext after the iv seed. */ /* 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 /* len is set to the length of the cipher plain text to be encrpyted
which is (in this case) identical to original packet lentgh */ which is (in this case) identical to original packet lentgh */
len = in_len; len = in_len;
/* The assembly buffer is a source for encrypting data. /* The assembly buffer is a source for encrypting data.
* The whole contents of assembly are encrypted. */ * The whole contents of assembly are encrypted. */
memcpy( assembly, inbuf, in_len); memcpy( assembly, inbuf, in_len);
/* Need at least one encrypted byte at the end for the padding. */ /* 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. */ len2 = ( (len / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; /* Round up to next whole AES adding at least one byte. */
padding = (len2-len); padding = (len2-len);
assembly[len2 - 1] = padding; assembly[len2 - 1] = padding;
traceEvent(TRACE_DEBUG, "padding = %u, seed = %016llx", padding, iv_seed); traceEvent(TRACE_DEBUG, "padding = %u, seed = %016llx", padding, iv_seed);
set_aes_cbc_iv(priv, enc_ivec, iv_seed); set_aes_cbc_iv(priv, enc_ivec, iv_seed);
EVP_CIPHER_CTX *ctx = priv->enc_ctx; EVP_CIPHER_CTX *ctx = priv->enc_ctx;
int evp_len; int evp_len;
int evp_ciphertext_len; int evp_ciphertext_len;
if (1 == EVP_EncryptInit_ex(ctx, priv->cipher, NULL, priv->key, enc_ivec)) { 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_CIPHER_CTX_set_padding(ctx, 0)) {
if (1 == EVP_EncryptUpdate(ctx, outbuf + TRANSOP_AES_PREAMBLE_SIZE, &evp_len, assembly, len2)) { if (1 == EVP_EncryptUpdate(ctx, outbuf + TRANSOP_AES_PREAMBLE_SIZE, &evp_len, assembly, len2)) {
evp_ciphertext_len = evp_len; 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; evp_ciphertext_len += evp_len;
if ( evp_ciphertext_len != len2) if ( evp_ciphertext_len != len2)
traceEvent (TRACE_ERROR, "encode_aes openssl encryption: encrypted %u bytes where %u were expected.\n", traceEvent (TRACE_ERROR, "encode_aes openssl encryption: encrypted %u bytes where %u were expected.\n",
evp_ciphertext_len, len2); 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());
} else } else
traceEvent(TRACE_ERROR, "encode_aes openssl init: %s\n", openssl_err_as_string()); traceEvent(TRACE_ERROR, "encode_aes openssl final encryption: %s\n", openssl_err_as_string());
EVP_CIPHER_CTX_reset(ctx); } else
traceEvent(TRACE_ERROR, "encode_aes openssl encrpytion: %s\n", openssl_err_as_string());
len2 += TRANSOP_AES_PREAMBLE_SIZE; /* size of data carried in UDP. */ } else
} else traceEvent(TRACE_ERROR, "encode_aes openssl padding setup: %s\n", openssl_err_as_string());
traceEvent(TRACE_ERROR, "encode_aes outbuf too small."); } 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 } 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 */ /* See transop_encode_aes for packet format */
static int transop_decode_aes( n2n_trans_op_t * arg, static int transop_decode_aes( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len, size_t in_len,
const uint8_t * peer_mac) { const uint8_t * peer_mac) {
int len=0; int len=0;
transop_aes_t * priv = (transop_aes_t *)arg->priv; transop_aes_t * priv = (transop_aes_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE]; 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 */ && (in_len >= TRANSOP_AES_PREAMBLE_SIZE) /* Has at least version, iv seed */
) )
{ {
size_t rem=in_len; size_t rem=in_len;
size_t idx=0; size_t idx=0;
uint8_t aes_enc_ver=0; uint8_t aes_enc_ver=0;
uint64_t iv_seed=0; uint64_t iv_seed=0;
/* Get the encoding version to make sure it is supported */ /* Get the encoding version to make sure it is supported */
decode_uint8( &aes_enc_ver, inbuf, &rem, &idx ); 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 */ /* Get the IV seed */
decode_buf((uint8_t *)&iv_seed, TRANSOP_AES_IV_SEED_SIZE, inbuf, &rem, &idx); 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); traceEvent(TRACE_DEBUG, "decode_aes %lu with seed %016llx", in_len, iv_seed);
len = (in_len - TRANSOP_AES_PREAMBLE_SIZE); len = (in_len - TRANSOP_AES_PREAMBLE_SIZE);
if ( 0 == (len % AES_BLOCK_SIZE)) { if ( 0 == (len % AES_BLOCK_SIZE)) {
uint8_t padding; uint8_t padding;
n2n_aes_ivec_t dec_ivec = {0}; n2n_aes_ivec_t dec_ivec = {0};
set_aes_cbc_iv(priv, dec_ivec, iv_seed); set_aes_cbc_iv(priv, dec_ivec, iv_seed);
EVP_CIPHER_CTX *ctx = priv->dec_ctx; EVP_CIPHER_CTX *ctx = priv->dec_ctx;
int evp_len; int evp_len;
int evp_plaintext_len; int evp_plaintext_len;
if (1 == EVP_DecryptInit_ex(ctx, priv->cipher, NULL, priv->key, dec_ivec)) { 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_CIPHER_CTX_set_padding(ctx, 0)) {
if (1 == EVP_DecryptUpdate(ctx, assembly, &evp_len, inbuf + TRANSOP_AES_PREAMBLE_SIZE, len)) { if (1 == EVP_DecryptUpdate(ctx, assembly, &evp_len, inbuf + TRANSOP_AES_PREAMBLE_SIZE, len)) {
evp_plaintext_len = evp_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; evp_plaintext_len += evp_len;
if ( evp_plaintext_len != len) if ( evp_plaintext_len != len)
traceEvent (TRACE_ERROR, "decode_aes openssl decryption: decrypted %u bytes where %u were expected.\n", traceEvent (TRACE_ERROR, "decode_aes openssl decryption: decrypted %u bytes where %u were expected.\n",
evp_plaintext_len, len); 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());
} else } else
traceEvent(TRACE_ERROR, "decode_aes openssl init: %s\n", openssl_err_as_string()); traceEvent(TRACE_ERROR, "decode_aes openssl final decryption: %s\n", openssl_err_as_string());
EVP_CIPHER_CTX_reset(ctx); } else
traceEvent(TRACE_ERROR, "decode_aes openssl decrpytion: %s\n", openssl_err_as_string());
/* last byte is how much was padding: max value should be } else
* AES_BLOCKSIZE-1 */ traceEvent(TRACE_ERROR, "decode_aes openssl padding setup: %s\n", openssl_err_as_string());
padding = assembly[ len-1 ] & 0xff; } else
traceEvent(TRACE_ERROR, "decode_aes openssl init: %s\n", openssl_err_as_string());
if ( len >= padding) EVP_CIPHER_CTX_reset(ctx);
{
/* strictly speaking for this to be an ethernet packet /* last byte is how much was padding: max value should be
* it is going to need to be even bigger; but this is * AES_BLOCKSIZE-1 */
* enough to prevent segfaults. */ padding = assembly[ len-1 ] & 0xff;
traceEvent(TRACE_DEBUG, "padding = %u", padding);
len -= padding; if ( len >= padding)
{
memcpy( outbuf, /* strictly speaking for this to be an ethernet packet
assembly, * it is going to need to be even bigger; but this is
len); * enough to prevent segfaults. */
} else traceEvent(TRACE_DEBUG, "padding = %u", padding);
traceEvent(TRACE_WARNING, "UDP payload decryption failed."); len -= padding;
} else {
traceEvent(TRACE_WARNING, "Encrypted length %d is not a multiple of AES_BLOCK_SIZE (%d)", len, AES_BLOCK_SIZE); memcpy( outbuf,
len = 0; assembly,
} len);
} else } else
traceEvent(TRACE_ERROR, "decode_aes unsupported aes version %u.", aes_enc_ver); 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 } 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) { 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_bytes;
size_t aes_key_size_bits; size_t aes_key_size_bits;
uint8_t key_mat_buf[SHA512_DIGEST_LENGTH + SHA256_DIGEST_LENGTH]; uint8_t key_mat_buf[SHA512_DIGEST_LENGTH + SHA256_DIGEST_LENGTH];
size_t key_mat_buf_length; size_t key_mat_buf_length;
/* Clear out any old possibly longer key matter. */ /* Clear out any old possibly longer key matter. */
memset( &(priv->key), 0, sizeof(priv->key) ); memset( &(priv->key), 0, sizeof(priv->key) );
memset( &(priv->iv_enc_key), 0, sizeof(priv->iv_enc_key) ); memset( &(priv->iv_enc_key), 0, sizeof(priv->iv_enc_key) );
memset( &(priv->iv_pad_val), 0, sizeof(priv->iv_pad_val) ); memset( &(priv->iv_pad_val), 0, sizeof(priv->iv_pad_val) );
/* Let the user choose the degree of encryption: /* Let the user choose the degree of encryption:
* Long input keys will pick AES192 or AES256 with more robust but expensive 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 * 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). * also to derive some additional material (key for IV encrpytion, IV padding).
* *
* The following scheme for key setup was discussed on github: * The following scheme for key setup was discussed on github:
* https://github.com/ntop/n2n/issues/101 * https://github.com/ntop/n2n/issues/101
*/ */
/* create a working buffer of maximal occuring hashes size and generate /* create a working buffer of maximal occuring hashes size and generate
* the hashes for the aes key material, key_mat_buf_lengh indicates the * the hashes for the aes key material, key_mat_buf_lengh indicates the
* actual "filling level" of the buffer * actual "filling level" of the buffer
*/ */
if (key_size >= 65) if (key_size >= 65)
{ {
priv->cipher = EVP_aes_256_cbc(); priv->cipher = EVP_aes_256_cbc();
aes_key_size_bytes = AES256_KEY_BYTES; aes_key_size_bytes = AES256_KEY_BYTES;
SHA512(key, key_size, key_mat_buf); SHA512(key, key_size, key_mat_buf);
key_mat_buf_length = SHA512_DIGEST_LENGTH; key_mat_buf_length = SHA512_DIGEST_LENGTH;
} }
else if (key_size >= 44) else if (key_size >= 44)
{ {
priv->cipher = EVP_aes_192_cbc(); priv->cipher = EVP_aes_192_cbc();
aes_key_size_bytes = AES192_KEY_BYTES; aes_key_size_bytes = AES192_KEY_BYTES;
SHA384(key, key_size, key_mat_buf); SHA384(key, key_size, key_mat_buf);
/* append a hash of the first hash to create enough material for IV padding */ /* 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); SHA256(key_mat_buf, SHA384_DIGEST_LENGTH, key_mat_buf + SHA384_DIGEST_LENGTH);
key_mat_buf_length = SHA384_DIGEST_LENGTH + SHA256_DIGEST_LENGTH; key_mat_buf_length = SHA384_DIGEST_LENGTH + SHA256_DIGEST_LENGTH;
} }
else else
{ {
priv->cipher = EVP_aes_128_cbc(); priv->cipher = EVP_aes_128_cbc();
aes_key_size_bytes = AES128_KEY_BYTES; aes_key_size_bytes = AES128_KEY_BYTES;
SHA256(key, key_size, key_mat_buf); SHA256(key, key_size, key_mat_buf);
/* append a hash of the first hash to create enough material for IV padding */ /* 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); SHA256(key_mat_buf, SHA256_DIGEST_LENGTH, key_mat_buf + SHA256_DIGEST_LENGTH);
key_mat_buf_length = 2 * SHA256_DIGEST_LENGTH; key_mat_buf_length = 2 * SHA256_DIGEST_LENGTH;
} }
/* is there enough material available? */ /* 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 */ /* this should never happen */
traceEvent( TRACE_ERROR, "AES missing %u bits hashed key material\n", 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); (aes_key_size_bytes + TRANSOP_AES_IV_KEY_BYTES + TRANSOP_AES_IV_PADDING_SIZE - key_mat_buf_length) * 8);
return(1); return(1);
} }
/* setup of key, used for the CBC encryption */ /* setup of key, used for the CBC encryption */
aes_key_size_bits = 8 * aes_key_size_bytes; aes_key_size_bits = 8 * aes_key_size_bytes;
memcpy (priv->key, key_mat_buf, 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 */ /* 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)); 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); 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", traceEvent(TRACE_DEBUG, "AES %u bits setup completed\n",
aes_key_size_bits); aes_key_size_bits);
return(0); 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) {}

Loading…
Cancel
Save