Browse Source

readability code clean-up (#543)

pull/554/head
Logan oos Even 4 years ago
committed by GitHub
parent
commit
30a1ff9313
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 344
      src/transform_aes.c
  2. 223
      src/transform_cc20.c
  3. 101
      src/transform_null.c
  4. 224
      src/transform_speck.c
  5. 309
      src/transform_tf.c

344
src/transform_aes.c

@ -27,27 +27,29 @@
// might encounter an issue with lower values here // might encounter an issue with lower values here
#define AES_PREAMBLE_SIZE (AES_BLOCK_SIZE) #define AES_PREAMBLE_SIZE (AES_BLOCK_SIZE)
// cts/cbc mode is being used with random value prepended to plaintext // cts/cbc mode is being used with random value prepended to plaintext
// instead of iv so, actual iv is aes_null_iv // instead of iv so, actual iv is aes_null_iv
const uint8_t aes_null_iv[AES_IV_SIZE] = {0}; const uint8_t aes_null_iv[AES_IV_SIZE] = { 0 };
typedef struct transop_aes { typedef struct transop_aes {
aes_context_t *ctx; aes_context_t *ctx;
} 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;
if(priv->ctx) aes_deinit(priv->ctx); if(priv->ctx)
aes_deinit(priv->ctx);
if(priv) free(priv); if(priv)
free(priv);
return 0; return 0;
} }
/* ****************************************************** */
// the aes packet format consists of // the aes packet format consists of
// //
@ -58,187 +60,187 @@ static int transop_deinit_aes(n2n_trans_op_t *arg) {
// [VV|DDDDDDDDDDDDDDDDDDDDD] // [VV|DDDDDDDDDDDDDDDDDDDDD]
// | <---- 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) {
transop_aes_t * priv = (transop_aes_t *)arg->priv; transop_aes_t *priv = (transop_aes_t *)arg->priv;
// 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
uint8_t assembly[N2N_PKT_BUF_SIZE]; uint8_t assembly[N2N_PKT_BUF_SIZE];
size_t idx = 0; size_t idx = 0;
int padded_len; int padded_len;
uint8_t padding; uint8_t padding;
uint8_t buf[AES_BLOCK_SIZE]; uint8_t buf[AES_BLOCK_SIZE];
if(in_len <= N2N_PKT_BUF_SIZE) { if(in_len <= N2N_PKT_BUF_SIZE) {
if((in_len + AES_PREAMBLE_SIZE + AES_BLOCK_SIZE) <= out_len) { if((in_len + AES_PREAMBLE_SIZE + AES_BLOCK_SIZE) <= out_len) {
traceEvent(TRACE_DEBUG, "transop_encode_aes %lu bytes plaintext", in_len);
traceEvent(TRACE_DEBUG, "transop_encode_aes %lu bytes plaintext", in_len);
// full block sized random value (128 bit)
// full block sized random value (128 bit) encode_uint64(assembly, &idx, n2n_rand());
encode_uint64(assembly, &idx, n2n_rand()); encode_uint64(assembly, &idx, n2n_rand());
encode_uint64(assembly, &idx, n2n_rand());
// adjust for maybe differently chosen AES_PREAMBLE_SIZE // adjust for maybe differently chosen AES_PREAMBLE_SIZE
idx = AES_PREAMBLE_SIZE; idx = AES_PREAMBLE_SIZE;
// the plaintext data // the plaintext data
encode_buf(assembly, &idx, inbuf, in_len); encode_buf(assembly, &idx, inbuf, in_len);
// round up to next whole AES block size // round up to next whole AES block size
padded_len = (((idx - 1) / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; padded_len = (((idx - 1) / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
padding = (padded_len-idx); padding = (padded_len-idx);
// pad the following bytes with zero, fixed length (AES_BLOCK_SIZE) seems to compile
// to slightly faster code than run-time dependant 'padding' // pad the following bytes with zero, fixed length (AES_BLOCK_SIZE) seems to compile
memset (assembly + idx, 0, AES_BLOCK_SIZE); // to slightly faster code than run-time dependant 'padding'
memset(assembly + idx, 0, AES_BLOCK_SIZE);
aes_cbc_encrypt(outbuf, assembly, padded_len, aes_null_iv, priv->ctx);
aes_cbc_encrypt(outbuf, assembly, padded_len, aes_null_iv, priv->ctx);
if(padding) {
// exchange last two cipher blocks if(padding) {
memcpy (buf, outbuf+padded_len - AES_BLOCK_SIZE, AES_BLOCK_SIZE); // exchange last two cipher blocks
memcpy (outbuf + padded_len - AES_BLOCK_SIZE, outbuf + padded_len - 2 * AES_BLOCK_SIZE, AES_BLOCK_SIZE); memcpy(buf, outbuf+padded_len - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
memcpy (outbuf + padded_len - 2 * AES_BLOCK_SIZE, buf, AES_BLOCK_SIZE); memcpy(outbuf + padded_len - AES_BLOCK_SIZE, outbuf + padded_len - 2 * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
} memcpy(outbuf + padded_len - 2 * AES_BLOCK_SIZE, buf, AES_BLOCK_SIZE);
}
} else
traceEvent(TRACE_ERROR, "transop_encode_aes outbuf too small");
} else } else
traceEvent(TRACE_ERROR, "transop_encode_aes outbuf too small");
} else
traceEvent(TRACE_ERROR, "transop_encode_aes inbuf too big to encrypt"); traceEvent(TRACE_ERROR, "transop_encode_aes inbuf too big to encrypt");
return idx; return idx;
} }
/* ****************************************************** */
// 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) {
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];
uint8_t rest; uint8_t rest;
size_t penultimate_block; size_t penultimate_block;
uint8_t buf[AES_BLOCK_SIZE]; uint8_t buf[AES_BLOCK_SIZE];
int len=-1; int len = -1;
if( ((in_len - AES_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) // cipher text fits in assembly if(((in_len - AES_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */
&& (in_len >= AES_PREAMBLE_SIZE) // has at least random number && (in_len >= AES_PREAMBLE_SIZE) /* has at least random number */
&& (in_len >= AES_BLOCK_SIZE) // minimum size requirement for cipher text stealing && (in_len >= AES_BLOCK_SIZE)) { /* minimum size requirement for cipher text stealing */
) { traceEvent(TRACE_DEBUG, "transop_decode_aes %lu bytes ciphertext", in_len);
traceEvent(TRACE_DEBUG, "transop_decode_aes %lu bytes ciphertext", in_len); rest = in_len % AES_BLOCK_SIZE;
if(rest) { /* cipher text stealing */
rest = in_len % AES_BLOCK_SIZE; penultimate_block = ((in_len / AES_BLOCK_SIZE) - 1) * AES_BLOCK_SIZE;
if(rest) {
// cipher text stealing // everything normal up to penultimate block
penultimate_block = ((in_len / AES_BLOCK_SIZE) - 1) * AES_BLOCK_SIZE; memcpy(assembly, inbuf, penultimate_block);
// everything normal up to penultimate block
memcpy(assembly, inbuf, penultimate_block); // prepare new penultimate block in buf
// prepare new penultimate block in buf aes_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx);
aes_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx); memcpy(buf, inbuf + in_len - rest, rest);
memcpy(buf, inbuf + in_len - rest, rest);
// former penultimate block becomes new ultimate block // former penultimate block becomes new ultimate block
memcpy(assembly + penultimate_block + AES_BLOCK_SIZE, inbuf + penultimate_block, AES_BLOCK_SIZE); memcpy(assembly + penultimate_block + AES_BLOCK_SIZE, inbuf + penultimate_block, AES_BLOCK_SIZE);
// write new penultimate block from buf
memcpy(assembly + penultimate_block, buf, AES_BLOCK_SIZE); // write new penultimate block from buf
// regular cbc decryption on the re-arranged ciphertext memcpy(assembly + penultimate_block, buf, AES_BLOCK_SIZE);
aes_cbc_decrypt(assembly, assembly, in_len + AES_BLOCK_SIZE - rest, aes_null_iv, priv->ctx);
// check for expected zero padding and give a warning otherwise // regular cbc decryption of the re-arranged ciphertext
if (memcmp(assembly + in_len, aes_null_iv, AES_BLOCK_SIZE - rest)) { aes_cbc_decrypt(assembly, assembly, in_len + AES_BLOCK_SIZE - rest, aes_null_iv, priv->ctx);
traceEvent(TRACE_WARNING, "transop_decode_aes payload decryption failed with unexpected cipher text stealing padding");
return -1; // check for expected zero padding and give a warning otherwise
} if(memcmp(assembly + in_len, aes_null_iv, AES_BLOCK_SIZE - rest)) {
traceEvent(TRACE_WARNING, "transop_decode_aes payload decryption failed with unexpected cipher text stealing padding");
return -1;
}
} else {
// regular cbc decryption on multiple block-sized payload
aes_cbc_decrypt(assembly, inbuf, in_len, aes_null_iv, priv->ctx);
}
len = in_len - AES_PREAMBLE_SIZE;
memcpy(outbuf, assembly + AES_PREAMBLE_SIZE, len);
} else
traceEvent(TRACE_ERROR, "transop_decode_aes inbuf wrong size (%ul) to decrypt", in_len);
return len;
}
static int setup_aes_key (transop_aes_t *priv, const uint8_t *password, ssize_t password_len) {
unsigned char key_mat[32]; /* maximum aes key length, equals hash length */
unsigned char *key;
size_t key_size;
// let the user choose the degree of encryption:
// long input passwords will pick AES192 or AES256 with more robust but expensive encryption
// the input password always gets hashed to make a more unpredictable use of the key space
// just think of usually reset MSB of ASCII coded password bytes
pearson_hash_256(key_mat, password, password_len);
// the length-dependant scheme for key setup was discussed on github:
// https://github.com/ntop/n2n/issues/101 -- as no iv encryption required
// anymore, the key-size trigger values were roughly halved
if(password_len >= 33) {
key_size = AES256_KEY_BYTES; /* 256 bit */
} else if(password_len >= 23) {
key_size = AES192_KEY_BYTES; /* 192 bit */
} else { } else {
// regular cbc decryption on multiple block-sized payload key_size = AES128_KEY_BYTES; /* 128 bit */
aes_cbc_decrypt(assembly, inbuf, in_len, aes_null_iv, priv->ctx);
} }
len = in_len - AES_PREAMBLE_SIZE;
memcpy(outbuf,
assembly + AES_PREAMBLE_SIZE,
len);
} else
traceEvent(TRACE_ERROR, "transop_decode_aes inbuf wrong size (%ul) to decrypt", in_len);
return len;
}
/* ****************************************************** */ // and use the last key-sized part of the hash as aes key
key = key_mat + sizeof(key_mat) - key_size;
static int setup_aes_key(transop_aes_t *priv, const uint8_t *password, ssize_t password_len) {
// setup the key and have corresponding context created
unsigned char key_mat[32]; // maximum aes key length, equals hash length if(aes_init (key, key_size, &(priv->ctx))) {
unsigned char *key; traceEvent(TRACE_ERROR, "setup_aes_key %u-bit key setup unsuccessful", key_size * 8);
size_t key_size; return -1;
}
// let the user choose the degree of encryption: traceEvent(TRACE_DEBUG, "setup_aes_key %u-bit key setup completed", key_size * 8);
// long input passwords will pick AES192 or AES256 with more robust but expensive encryption
return 0;
// the input password always gets hashed to make a more unpredictable use of the key space
// just think of usually reset MSB of ASCII coded password bytes
pearson_hash_256(key_mat, password, password_len);
// the length-dependant scheme for key setup was discussed on github:
// https://github.com/ntop/n2n/issues/101 -- as no iv encryption required
// anymore, the key-size trigger values were roughly halved
if(password_len >= 33) {
key_size = AES256_KEY_BYTES; // 256 bit
} else if(password_len >= 23) {
key_size = AES192_KEY_BYTES; // 192 bit
} else {
key_size = AES128_KEY_BYTES; // 128 bit
}
// and use the last key-sized part of the hash as aes key
key = key_mat + sizeof(key_mat) - key_size;
// setup the key and have corresponding context created
if (aes_init (key, key_size, &(priv->ctx))) {
traceEvent(TRACE_ERROR, "setup_aes_key %u-bit key setup unsuccessful",
key_size * 8);
return -1;
}
traceEvent(TRACE_DEBUG, "setup_aes_key %u-bit key setup completed",
key_size * 8);
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) {
// no tick action
}
/* ****************************************************** */
// AES initialization function // AES initialization function
int n2n_transop_aes_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { int n2n_transop_aes_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_aes_t *priv; transop_aes_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key; const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key); size_t encrypt_key_len = strlen(conf->encrypt_key);
memset(ttt, 0, sizeof(*ttt)); memset(ttt, 0, sizeof(*ttt));
ttt->transform_id = N2N_TRANSFORM_ID_AES; ttt->transform_id = N2N_TRANSFORM_ID_AES;
ttt->tick = transop_tick_aes; ttt->tick = transop_tick_aes;
ttt->deinit = transop_deinit_aes; ttt->deinit = transop_deinit_aes;
ttt->fwd = transop_encode_aes; ttt->fwd = transop_encode_aes;
ttt->rev = transop_decode_aes; ttt->rev = transop_decode_aes;
priv = (transop_aes_t*) calloc(1, sizeof(transop_aes_t)); priv = (transop_aes_t*)calloc(1, sizeof(transop_aes_t));
if(!priv) { if(!priv) {
traceEvent(TRACE_ERROR, "n2n_transop_aes_init cannot allocate transop_aes_t memory"); traceEvent(TRACE_ERROR, "n2n_transop_aes_init cannot allocate transop_aes_t memory");
return(-1); return -1;
} }
ttt->priv = priv; ttt->priv = priv;
// setup the cipher and key // setup the cipher and key
return(setup_aes_key(priv, encrypt_key, encrypt_key_len)); return setup_aes_key(priv, encrypt_key, encrypt_key_len);
} }

223
src/transform_cc20.c

@ -20,160 +20,155 @@
#include "n2n.h" #include "n2n.h"
/* ChaCha20 plaintext preamble */ // ChaCha20 plaintext preamble
#define CC20_PREAMBLE_SIZE (CC20_IV_SIZE) #define CC20_PREAMBLE_SIZE (CC20_IV_SIZE)
typedef struct transop_cc20 { typedef struct transop_cc20 {
cc20_context_t *ctx; cc20_context_t *ctx;
} transop_cc20_t; } transop_cc20_t;
/* ****************************************************** */
static int transop_deinit_cc20(n2n_trans_op_t *arg) { static int transop_deinit_cc20 (n2n_trans_op_t *arg) {
transop_cc20_t *priv = (transop_cc20_t *)arg->priv; transop_cc20_t *priv = (transop_cc20_t *)arg->priv;
if(priv->ctx) if(priv->ctx)
cc20_deinit(priv->ctx); cc20_deinit(priv->ctx);
if(priv) if(priv)
free(priv); free(priv);
return 0; return 0;
} }
/* ****************************************************** */
/** The ChaCha20 packet format consists of:
*
* - a 128-bit random IV
* - encrypted payload.
*
* [IIII|DDDDDDDDDDDDDDDDDDDDD]
* |<---- encrypted ---->|
*/
static int transop_encode_cc20(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=-1;
transop_cc20_t * priv = (transop_cc20_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE] = {0};
if(in_len <= N2N_PKT_BUF_SIZE) {
if((in_len + CC20_PREAMBLE_SIZE) <= out_len) {
size_t idx=0;
traceEvent(TRACE_DEBUG, "encode_cc20 %lu bytes", in_len); // the ChaCha20 packet format consists of
//
// full IV sized random value (128 bit) // - a 128-bit random iv
encode_uint64(outbuf, &idx, n2n_rand()); // - encrypted payload
encode_uint64(outbuf, &idx, n2n_rand()); //
// [IIII|DDDDDDDDDDDDDDDDDDDDD]
len = in_len; // |<---- encrypted ---->|
cc20_crypt(outbuf + CC20_PREAMBLE_SIZE, //
inbuf, static int transop_encode_cc20 (n2n_trans_op_t *arg,
in_len, uint8_t *outbuf,
outbuf, // IV size_t out_len,
priv->ctx); const uint8_t *inbuf,
size_t in_len,
len += CC20_PREAMBLE_SIZE; /* size of data carried in UDP. */ const uint8_t *peer_mac) {
int len = -1;
transop_cc20_t *priv = (transop_cc20_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE] = { 0 };
if(in_len <= N2N_PKT_BUF_SIZE) {
if((in_len + CC20_PREAMBLE_SIZE) <= out_len) {
size_t idx = 0;
traceEvent(TRACE_DEBUG, "encode_cc20 %lu bytes", in_len);
// full iv sized random value (128 bit)
encode_uint64(outbuf, &idx, n2n_rand());
encode_uint64(outbuf, &idx, n2n_rand());
len = in_len;
cc20_crypt(outbuf + CC20_PREAMBLE_SIZE,
inbuf,
in_len,
outbuf, /* iv */
priv->ctx);
// size of datacarried in UDP
len += CC20_PREAMBLE_SIZE;
} else
traceEvent(TRACE_ERROR, "encode_cc20 outbuf too small.");
} else } else
traceEvent(TRACE_ERROR, "encode_cc20 outbuf too small."); traceEvent(TRACE_ERROR, "encode_cc20 inbuf too big to encrypt.");
} else
traceEvent(TRACE_ERROR, "encode_cc20 inbuf too big to encrypt.");
return len; return len;
} }
/* ****************************************************** */
/* See transop_encode_cc20 for packet format */
static int transop_decode_cc20(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; // see transop_encode_cc20 for packet format
transop_cc20_t * priv = (transop_cc20_t *)arg->priv; static int transop_decode_cc20 (n2n_trans_op_t *arg,
uint8_t assembly[N2N_PKT_BUF_SIZE]; uint8_t *outbuf,
size_t out_len,
const uint8_t *inbuf,
size_t in_len,
const uint8_t *peer_mac) {
if(((in_len - CC20_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in assembly */ int len = 0;
&& (in_len >= CC20_PREAMBLE_SIZE) /* Has at least iv */ transop_cc20_t *priv = (transop_cc20_t *)arg->priv;
) uint8_t assembly[N2N_PKT_BUF_SIZE];
{
size_t rem=in_len;
size_t idx=0;
traceEvent(TRACE_DEBUG, "decode_cc20 %lu bytes", in_len); if(((in_len - CC20_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */
&& (in_len >= CC20_PREAMBLE_SIZE)) { /* has at least iv */
size_t rem = in_len;
size_t idx = 0;
len = (in_len - CC20_PREAMBLE_SIZE); traceEvent(TRACE_DEBUG, "decode_cc20 %lu bytes", in_len);
cc20_crypt(outbuf, len = (in_len - CC20_PREAMBLE_SIZE);
inbuf + CC20_PREAMBLE_SIZE,
in_len,
inbuf, // IV
priv->ctx);
} else cc20_crypt(outbuf,
traceEvent(TRACE_ERROR, "decode_cc20 inbuf wrong size (%ul) to decrypt.", in_len); inbuf + CC20_PREAMBLE_SIZE,
in_len,
inbuf, /* iv */
priv->ctx);
} else
traceEvent(TRACE_ERROR, "decode_cc20 inbuf wrong size (%ul) to decrypt.", in_len);
return len; return len;
} }
/* ****************************************************** */
static int setup_cc20_key(transop_cc20_t *priv, const uint8_t *password, ssize_t password_len) { static int setup_cc20_key (transop_cc20_t *priv, const uint8_t *password, ssize_t password_len) {
uint8_t key_mat[CC20_KEY_BYTES]; uint8_t key_mat[CC20_KEY_BYTES];
/* The input key always gets hashed to make a more unpredictable and more complete use of the key space */ // the input key always gets hashed to make a more unpredictable and more complete use of the key space
pearson_hash_256(key_mat, password, password_len); pearson_hash_256(key_mat, password, password_len);
if(cc20_init(key_mat, &(priv->ctx))) { if(cc20_init(key_mat, &(priv->ctx))) {
traceEvent(TRACE_ERROR, "setup_cc20_key setup unsuccessful"); traceEvent(TRACE_ERROR, "setup_cc20_key setup unsuccessful");
return -1; return -1;
} }
traceEvent(TRACE_DEBUG, "setup_cc20_key completed"); traceEvent(TRACE_DEBUG, "setup_cc20_key completed");
return 0; return 0;
} }
/* ****************************************************** */
static void transop_tick_cc20(n2n_trans_op_t * arg, time_t now) { ; } static void transop_tick_cc20 (n2n_trans_op_t *arg, time_t now) {
// no tick action
}
/* ****************************************************** */
/* ChaCha20 initialization function */ // ChaCha20 initialization function
int n2n_transop_cc20_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { int n2n_transop_cc20_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_cc20_t *priv; transop_cc20_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key; const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key); size_t encrypt_key_len = strlen(conf->encrypt_key);
memset(ttt, 0, sizeof(*ttt)); memset(ttt, 0, sizeof(*ttt));
ttt->transform_id = N2N_TRANSFORM_ID_CHACHA20; ttt->transform_id = N2N_TRANSFORM_ID_CHACHA20;
ttt->tick = transop_tick_cc20; ttt->tick = transop_tick_cc20;
ttt->deinit = transop_deinit_cc20; ttt->deinit = transop_deinit_cc20;
ttt->fwd = transop_encode_cc20; ttt->fwd = transop_encode_cc20;
ttt->rev = transop_decode_cc20; ttt->rev = transop_decode_cc20;
priv = (transop_cc20_t*) calloc(1, sizeof(transop_cc20_t)); priv = (transop_cc20_t*)calloc(1, sizeof(transop_cc20_t));
if(!priv) { if(!priv) {
traceEvent(TRACE_ERROR, "cannot allocate transop_cc20_t memory"); traceEvent(TRACE_ERROR, "cannot allocate transop_cc20_t memory");
return(-1); return -1;
} }
ttt->priv = priv; ttt->priv = priv;
/* Setup the cipher and key */ // setup the cipher and key
return setup_cc20_key(priv, encrypt_key, encrypt_key_len); return setup_cc20_key(priv, encrypt_key, encrypt_key_len);
} }

101
src/transform_null.c

@ -16,71 +16,76 @@
* *
*/ */
#include "n2n.h" #include "n2n.h"
static int transop_deinit_null( n2n_trans_op_t * arg )
{ static int transop_deinit_null (n2n_trans_op_t *arg ) {
/* nothing to deallocate, nothing to release. */
return 0; // nothing to deallocate, nothing to release
return 0;
} }
static int transop_encode_null( n2n_trans_op_t * arg,
uint8_t * outbuf, static int transop_encode_null (n2n_trans_op_t *arg,
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 retval = -1; int retval = -1;
traceEvent( TRACE_DEBUG, "encode_null %lu", in_len ); traceEvent(TRACE_DEBUG, "encode_null %lu", in_len);
if ( out_len >= in_len ) if(out_len >= in_len) {
{ memcpy(outbuf, inbuf, in_len);
memcpy( outbuf, inbuf, in_len ); retval = in_len;
retval = in_len; } else {
} traceEvent(TRACE_DEBUG, "encode_null %lu too big for packet buffer", in_len);
else
{
traceEvent( TRACE_DEBUG, "encode_null %lu too big for packet buffer", in_len );
} }
return retval; return retval;
} }
static int transop_decode_null( n2n_trans_op_t * arg,
uint8_t * outbuf, static int transop_decode_null (n2n_trans_op_t *arg,
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 retval = -1; int retval = -1;
traceEvent( TRACE_DEBUG, "decode_null %lu", in_len ); traceEvent(TRACE_DEBUG, "decode_null %lu", in_len);
if ( out_len >= in_len ) if(out_len >= in_len) {
{ memcpy(outbuf, inbuf, in_len);
memcpy( outbuf, inbuf, in_len ); retval = in_len;
retval = in_len; } else {
} traceEvent(TRACE_DEBUG, "decode_null %lu too big for packet buffer", in_len);
else
{
traceEvent( TRACE_DEBUG, "decode_null %lu too big for packet buffer", in_len );
} }
return retval; return retval;
}
static void transop_tick_null (n2n_trans_op_t *arg, time_t now) {
// no tick action
} }
static void transop_tick_null(n2n_trans_op_t * arg, time_t now) {}
int n2n_transop_null_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { int n2n_transop_null_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
memset(ttt, 0, sizeof(n2n_trans_op_t) );
memset(ttt, 0, sizeof(n2n_trans_op_t));
ttt->transform_id = N2N_TRANSFORM_ID_NULL; ttt->transform_id = N2N_TRANSFORM_ID_NULL;
ttt->no_encryption = 1; ttt->no_encryption = 1;
ttt->deinit = transop_deinit_null; ttt->deinit = transop_deinit_null;
ttt->tick = transop_tick_null; ttt->tick = transop_tick_null;
ttt->fwd = transop_encode_null; ttt->fwd = transop_encode_null;
ttt->rev = transop_decode_null; ttt->rev = transop_decode_null;
return(0); return 0;
} }

224
src/transform_speck.c

@ -20,159 +20,157 @@
#include "n2n.h" #include "n2n.h"
/* Speck plaintext preamble */ // Speck plaintext preamble
#define TRANSOP_SPECK_PREAMBLE_SIZE (N2N_SPECK_IVEC_SIZE) #define TRANSOP_SPECK_PREAMBLE_SIZE (N2N_SPECK_IVEC_SIZE)
typedef struct transop_speck { typedef struct transop_speck {
speck_context_t *ctx; /* the round keys for payload encryption & decryption */ speck_context_t *ctx; /* the round keys for payload encryption & decryption */
} transop_speck_t; } transop_speck_t;
/* ****************************************************** */
static int transop_deinit_speck(n2n_trans_op_t *arg) { static int transop_deinit_speck (n2n_trans_op_t *arg) {
transop_speck_t *priv = (transop_speck_t *)arg->priv;
if(priv->ctx) speck_deinit(priv->ctx); transop_speck_t *priv = (transop_speck_t *)arg->priv;
if(priv) free (priv); if(priv->ctx)
speck_deinit(priv->ctx);
return 0; if(priv)
free(priv);
return 0;
} }
/* ****************************************************** */
/** The Speck packet format consists of: // the Speck packet format consists of
* //
* - a 128-bit random IV // - a 128-bit random iv
* - encrypted payload. // - encrypted payload
* //
* [IIII|DDDDDDDDDDDDDDDDDDDDD] // [IIII|DDDDDDDDDDDDDDDDDDDDD]
* |<---- encrypted ---->| // |<---- encrypted ---->|
*/ //
static int transop_encode_speck(n2n_trans_op_t * arg, static int transop_encode_speck (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=-1; int len = -1;
transop_speck_t * priv = (transop_speck_t *)arg->priv; transop_speck_t *priv = (transop_speck_t *)arg->priv;
if(in_len <= N2N_PKT_BUF_SIZE) { if(in_len <= N2N_PKT_BUF_SIZE) {
if((in_len + TRANSOP_SPECK_PREAMBLE_SIZE) <= out_len) { if((in_len + TRANSOP_SPECK_PREAMBLE_SIZE) <= out_len) {
size_t idx=0; size_t idx = 0;
traceEvent(TRACE_DEBUG, "encode_speck %lu bytes", in_len); traceEvent(TRACE_DEBUG, "encode_speck %lu bytes", in_len);
/* Generate and encode the IV. */ // generate and encode the iv
encode_uint64(outbuf, &idx, n2n_rand()); encode_uint64(outbuf, &idx, n2n_rand());
encode_uint64(outbuf, &idx, n2n_rand()); encode_uint64(outbuf, &idx, n2n_rand());
/* Encrypt the payload and write the ciphertext after the iv. */ // encrypt the payload and write the ciphertext after the iv
/* 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;
speck_ctr (outbuf + TRANSOP_SPECK_PREAMBLE_SIZE, // output starts right after the iv speck_ctr (outbuf + TRANSOP_SPECK_PREAMBLE_SIZE, /* output starts right after the iv */
inbuf, // input inbuf, /* input */
in_len, // len in_len, /* len */
outbuf, // iv (already encoded in outbuf, speck does not change it) outbuf, /* iv, already encoded in outbuf, speck does not change it */
priv->ctx); // ctx already setup with round keys priv->ctx); /* ctx already setup with round keys */
traceEvent(TRACE_DEBUG, "encode_speck: encrypted %u bytes.\n", in_len); traceEvent(TRACE_DEBUG, "encode_speck: encrypted %u bytes.\n", in_len);
len += TRANSOP_SPECK_PREAMBLE_SIZE; /* size of data carried in UDP. */ // size of data carried in UDP
len += TRANSOP_SPECK_PREAMBLE_SIZE;
} else
traceEvent(TRACE_ERROR, "encode_speck outbuf too small.");
} else } else
traceEvent(TRACE_ERROR, "encode_speck outbuf too small."); traceEvent(TRACE_ERROR, "encode_speck inbuf too big to encrypt.");
} else
traceEvent(TRACE_ERROR, "encode_speck inbuf too big to encrypt.");
return len; return len;
} }
/* ****************************************************** */
/* See transop_encode_speck for packet format */ // see transop_encode_speck for packet format
static int transop_decode_speck(n2n_trans_op_t * arg, static int transop_decode_speck (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_speck_t * priv = (transop_speck_t *)arg->priv; transop_speck_t *priv = (transop_speck_t *)arg->priv;
if(((in_len - TRANSOP_SPECK_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* Cipher text fits in buffer */ if(((in_len - TRANSOP_SPECK_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in buffer */
&& (in_len >= TRANSOP_SPECK_PREAMBLE_SIZE) /* Has at least iv */ && (in_len >= TRANSOP_SPECK_PREAMBLE_SIZE)) { /* has at least iv */
) size_t rem = in_len;
{ size_t idx = 0;
size_t rem=in_len;
size_t idx=0;
traceEvent(TRACE_DEBUG, "decode_speck %lu bytes", in_len); traceEvent(TRACE_DEBUG, "decode_speck %lu bytes", in_len);
len = (in_len - TRANSOP_SPECK_PREAMBLE_SIZE); len = (in_len - TRANSOP_SPECK_PREAMBLE_SIZE);
speck_ctr (outbuf, // output speck_ctr (outbuf, /* output */
inbuf + TRANSOP_SPECK_PREAMBLE_SIZE, // encrypted data starts right after preamble (IV) inbuf + TRANSOP_SPECK_PREAMBLE_SIZE, /* encrypted data starts right after preamble (iv) */
len, // len len, /* len */
inbuf, // IV can be found at input's beginning inbuf, /* iv can be found at input's beginning */
priv->ctx); // ctx already setup with round keys priv->ctx); /* ctx already setup with round keys */
traceEvent(TRACE_DEBUG, "decode_speck decrypted %u bytes.\n", len); traceEvent(TRACE_DEBUG, "decode_speck decrypted %u bytes.\n", len);
} else
} else traceEvent(TRACE_ERROR, "decode_speck inbuf wrong size (%ul) to decrypt.", in_len);
traceEvent(TRACE_ERROR, "decode_speck inbuf wrong size (%ul) to decrypt.", in_len);
return len; return len;
} }
/* ****************************************************** */
static int setup_speck_key(transop_speck_t *priv, const uint8_t *key, ssize_t key_size) { static int setup_speck_key (transop_speck_t *priv, const uint8_t *key, ssize_t key_size) {
uint8_t key_mat_buf[32]; uint8_t key_mat_buf[32];
/* the input key always gets hashed to make a more unpredictable and more complete use of the key space */ // the input key always gets hashed to make a more unpredictable and more complete use of the key space
pearson_hash_256(key_mat_buf, key, key_size); pearson_hash_256(key_mat_buf, key, key_size);
/* expand the key material to the context (= round keys) */ // expand the key material to the context (= round keys)
speck_init(key_mat_buf, &(priv->ctx)); speck_init(key_mat_buf, &(priv->ctx));
traceEvent(TRACE_DEBUG, "setup_speck_key completed\n"); traceEvent(TRACE_DEBUG, "setup_speck_key completed\n");
return 0; return 0;
} }
/* ****************************************************** */
static void transop_tick_speck(n2n_trans_op_t * arg, time_t now) { ; } static void transop_tick_speck (n2n_trans_op_t *arg, time_t now) {
// no tick action
}
/* ****************************************************** */
/* Speck initialization function */ // Speck initialization function
int n2n_transop_speck_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { int n2n_transop_speck_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_speck_t *priv; transop_speck_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key; const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key); size_t encrypt_key_len = strlen(conf->encrypt_key);
memset(ttt, 0, sizeof(*ttt)); memset(ttt, 0, sizeof(*ttt));
ttt->transform_id = N2N_TRANSFORM_ID_SPECK; ttt->transform_id = N2N_TRANSFORM_ID_SPECK;
ttt->tick = transop_tick_speck; ttt->tick = transop_tick_speck;
ttt->deinit = transop_deinit_speck; ttt->deinit = transop_deinit_speck;
ttt->fwd = transop_encode_speck; ttt->fwd = transop_encode_speck;
ttt->rev = transop_decode_speck; ttt->rev = transop_decode_speck;
priv = (transop_speck_t*) calloc(1, sizeof(transop_speck_t)); priv = (transop_speck_t*)calloc(1, sizeof(transop_speck_t));
if(!priv) { if(!priv) {
traceEvent(TRACE_ERROR, "n2n_transop_speck_init cannot allocate transop_speck_t memory"); traceEvent(TRACE_ERROR, "n2n_transop_speck_init cannot allocate transop_speck_t memory");
return(-1); return -1;
} }
ttt->priv = priv; ttt->priv = priv;
/* Setup the cipher and key */ // setup the cipher and key
return setup_speck_key(priv, encrypt_key, encrypt_key_len); return setup_speck_key(priv, encrypt_key, encrypt_key_len);
} }

309
src/transform_tf.c

@ -27,27 +27,29 @@
// might encounter an issue with lower values here // might encounter an issue with lower values here
#define TF_PREAMBLE_SIZE (TF_BLOCK_SIZE) #define TF_PREAMBLE_SIZE (TF_BLOCK_SIZE)
// cbc mode is being used with random value prepended to plaintext // cbc mode is being used with random value prepended to plaintext
// instead of iv so, actual iv is tf_null_iv // instead of iv so, actual iv is tf_null_iv
const uint8_t tf_null_iv[TF_IV_SIZE] = {0}; const uint8_t tf_null_iv[TF_IV_SIZE] = { 0 };
typedef struct transop_tf { typedef struct transop_tf {
tf_context_t *ctx; tf_context_t *ctx;
} transop_tf_t; } transop_tf_t;
/* ****************************************************** */
static int transop_deinit_tf(n2n_trans_op_t *arg) { static int transop_deinit_tf (n2n_trans_op_t *arg) {
transop_tf_t *priv = (transop_tf_t *)arg->priv;
transop_tf_t *priv = (transop_tf_t *)arg->priv;
if(priv->ctx) tf_deinit(priv->ctx); if(priv->ctx)
tf_deinit(priv->ctx);
if(priv) free(priv); if(priv)
free(priv);
return 0; return 0;
} }
/* ****************************************************** */
// the Twofish packet format consists of // the Twofish packet format consists of
// //
@ -58,174 +60,173 @@ static int transop_deinit_tf(n2n_trans_op_t *arg) {
// [VV|DDDDDDDDDDDDDDDDDDDDD] // [VV|DDDDDDDDDDDDDDDDDDDDD]
// | <---- encrypted ----> | // | <---- encrypted ----> |
// //
static int transop_encode_tf(n2n_trans_op_t * arg, static int transop_encode_tf (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) {
transop_tf_t * priv = (transop_tf_t *)arg->priv; transop_tf_t *priv = (transop_tf_t *)arg->priv;
// 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
uint8_t assembly[N2N_PKT_BUF_SIZE]; uint8_t assembly[N2N_PKT_BUF_SIZE];
size_t idx = 0; size_t idx = 0;
int padded_len; int padded_len;
uint8_t padding; uint8_t padding;
uint8_t buf[TF_BLOCK_SIZE]; uint8_t buf[TF_BLOCK_SIZE];
if(in_len <= N2N_PKT_BUF_SIZE) { if(in_len <= N2N_PKT_BUF_SIZE) {
if((in_len + TF_PREAMBLE_SIZE + TF_BLOCK_SIZE) <= out_len) { if((in_len + TF_PREAMBLE_SIZE + TF_BLOCK_SIZE) <= out_len) {
traceEvent(TRACE_DEBUG, "transop_encode_tf %lu bytes plaintext", in_len);
traceEvent(TRACE_DEBUG, "transop_encode_tf %lu bytes plaintext", in_len);
// full block sized random value (128 bit)
// full block sized random value (128 bit) encode_uint64(assembly, &idx, n2n_rand());
encode_uint64(assembly, &idx, n2n_rand()); encode_uint64(assembly, &idx, n2n_rand());
encode_uint64(assembly, &idx, n2n_rand());
// adjust for maybe differently chosen TF_PREAMBLE_SIZE
// adjust for maybe differently chosen TF_PREAMBLE_SIZE idx = TF_PREAMBLE_SIZE;
idx = TF_PREAMBLE_SIZE;
// the plaintext data
// the plaintext data encode_buf(assembly, &idx, inbuf, in_len);
encode_buf(assembly, &idx, inbuf, in_len);
// round up to next whole TF block size
// round up to next whole TF block size padded_len = (((idx - 1) / TF_BLOCK_SIZE) + 1) * TF_BLOCK_SIZE;
padded_len = (((idx - 1) / TF_BLOCK_SIZE) + 1) * TF_BLOCK_SIZE; padding = (padded_len-idx);
padding = (padded_len-idx);
// pad the following bytes with zero, fixed length (TF_BLOCK_SIZE) seems to compile // pad the following bytes with zero, fixed length (TF_BLOCK_SIZE) seems to compile
// to slightly faster code than run-time dependant 'padding' // to slightly faster code than run-time dependant 'padding'
memset (assembly + idx, 0, TF_BLOCK_SIZE); memset(assembly + idx, 0, TF_BLOCK_SIZE);
tf_cbc_encrypt(outbuf, assembly, padded_len, tf_null_iv, priv->ctx); tf_cbc_encrypt(outbuf, assembly, padded_len, tf_null_iv, priv->ctx);
if(padding) { if(padding) {
// exchange last two cipher blocks // exchange last two cipher blocks
memcpy (buf, outbuf + padded_len - TF_BLOCK_SIZE, TF_BLOCK_SIZE); memcpy(buf, outbuf + padded_len - TF_BLOCK_SIZE, TF_BLOCK_SIZE);
memcpy (outbuf + padded_len - TF_BLOCK_SIZE, outbuf + padded_len - 2 * TF_BLOCK_SIZE, TF_BLOCK_SIZE); memcpy(outbuf + padded_len - TF_BLOCK_SIZE, outbuf + padded_len - 2 * TF_BLOCK_SIZE, TF_BLOCK_SIZE);
memcpy (outbuf + padded_len - 2 * TF_BLOCK_SIZE, buf, TF_BLOCK_SIZE); memcpy(outbuf + padded_len - 2 * TF_BLOCK_SIZE, buf, TF_BLOCK_SIZE);
} }
} else
traceEvent(TRACE_ERROR, "transop_encode_tf outbuf too small");
} else } else
traceEvent(TRACE_ERROR, "transop_encode_tf outbuf too small"); traceEvent(TRACE_ERROR, "transop_encode_tf inbuf too big to encrypt");
} else
traceEvent(TRACE_ERROR, "transop_encode_tf inbuf too big to encrypt");
return idx; return idx;
} }
/* ****************************************************** */
// see transop_encode_tf for packet format // see transop_encode_tf for packet format
static int transop_decode_tf(n2n_trans_op_t * arg, static int transop_decode_tf (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) {
transop_tf_t * priv = (transop_tf_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE]; transop_tf_t *priv = (transop_tf_t *)arg->priv;
uint8_t assembly[N2N_PKT_BUF_SIZE];
uint8_t rest;
size_t penultimate_block; uint8_t rest;
uint8_t buf[TF_BLOCK_SIZE]; size_t penultimate_block;
int len=-1; uint8_t buf[TF_BLOCK_SIZE];
int len = -1;
if( ((in_len - TF_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) // cipher text fits in assembly
&& (in_len >= TF_PREAMBLE_SIZE) // has at least random number if(((in_len - TF_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */
&& (in_len >= TF_BLOCK_SIZE) // minimum size requirement for cipher text stealing && (in_len >= TF_PREAMBLE_SIZE) /* has at least random number */
) { && (in_len >= TF_BLOCK_SIZE)) { /* minimum size requirement for cipher text stealing */
traceEvent(TRACE_DEBUG, "transop_decode_tf %lu bytes ciphertext", in_len); traceEvent(TRACE_DEBUG, "transop_decode_tf %lu bytes ciphertext", in_len);
rest = in_len % TF_BLOCK_SIZE; rest = in_len % TF_BLOCK_SIZE;
if(rest) { if(rest) { /* cipher text stealing */
// cipher text stealing penultimate_block = ((in_len / TF_BLOCK_SIZE) - 1) * TF_BLOCK_SIZE;
penultimate_block = ((in_len / TF_BLOCK_SIZE) - 1) * TF_BLOCK_SIZE;
// everything normal up to penultimate block // everything normal up to penultimate block
memcpy(assembly, inbuf, penultimate_block); memcpy(assembly, inbuf, penultimate_block);
// prepare new penultimate block in buf
tf_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx); // prepare new penultimate block in buf
memcpy(buf, inbuf + in_len - rest, rest); tf_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx);
// former penultimate block becomes new ultimate block memcpy(buf, inbuf + in_len - rest, rest);
memcpy(assembly + penultimate_block + TF_BLOCK_SIZE, inbuf + penultimate_block, TF_BLOCK_SIZE);
// write new penultimate block from buf // former penultimate block becomes new ultimate block
memcpy(assembly + penultimate_block, buf, TF_BLOCK_SIZE); memcpy(assembly + penultimate_block + TF_BLOCK_SIZE, inbuf + penultimate_block, TF_BLOCK_SIZE);
// regular cbc decryption on the re-arranged ciphertext
// write new penultimate block from buf
tf_cbc_decrypt(assembly, assembly, in_len + TF_BLOCK_SIZE - rest, tf_null_iv, priv->ctx); memcpy(assembly + penultimate_block, buf, TF_BLOCK_SIZE);
// check for expected zero padding and give a warning otherwise // regular cbc decryption of the re-arranged ciphertext
if(memcmp(assembly + in_len, tf_null_iv, TF_BLOCK_SIZE - rest)) { tf_cbc_decrypt(assembly, assembly, in_len + TF_BLOCK_SIZE - rest, tf_null_iv, priv->ctx);
traceEvent(TRACE_WARNING, "transop_decode_tf payload decryption failed with unexpected cipher text stealing padding");
return -1; // check for expected zero padding and give a warning otherwise
} if(memcmp(assembly + in_len, tf_null_iv, TF_BLOCK_SIZE - rest)) {
} else { traceEvent(TRACE_WARNING, "transop_decode_tf payload decryption failed with unexpected cipher text stealing padding");
// regular cbc decryption on multiple block-sized payload return -1;
tf_cbc_decrypt(assembly, inbuf, in_len, tf_null_iv, priv->ctx); }
} } else {
len = in_len - TF_PREAMBLE_SIZE; // regular cbc decryption on multiple block-sized payload
memcpy(outbuf, tf_cbc_decrypt(assembly, inbuf, in_len, tf_null_iv, priv->ctx);
assembly + TF_PREAMBLE_SIZE, }
len); len = in_len - TF_PREAMBLE_SIZE;
} else memcpy(outbuf, assembly + TF_PREAMBLE_SIZE, len);
traceEvent(TRACE_ERROR, "transop_decode_tf inbuf wrong size (%ul) to decrypt", in_len); } else
traceEvent(TRACE_ERROR, "transop_decode_tf inbuf wrong size (%ul) to decrypt", in_len);
return len;
return len;
} }
/* ****************************************************** */
static int setup_tf_key(transop_tf_t *priv, const uint8_t *password, ssize_t password_len) { static int setup_tf_key (transop_tf_t *priv, const uint8_t *password, ssize_t password_len) {
unsigned char key[32]; // tf key length, equals hash length unsigned char key[32]; /* tf key length, equals hash length */
size_t key_size; size_t key_size;
// the input password always gets hashed to make a more unpredictable use of the key space // the input password always gets hashed to make a more unpredictable use of the key space
// just think of usually reset MSB of ASCII coded password bytes // just think of usually reset MSB of ASCII coded password bytes
pearson_hash_256(key, password, password_len); pearson_hash_256(key, password, password_len);
key_size = 32; // 256 bit key_size = 32; /* 256 bit */
// setup the key and have corresponding context created // setup the key and have corresponding context created
if(tf_init(key, key_size * 8, &(priv->ctx))) { if(tf_init(key, key_size * 8, &(priv->ctx))) {
traceEvent(TRACE_ERROR, "setup_tf_key %u-bit key setup unsuccessful", traceEvent(TRACE_ERROR, "setup_tf_key %u-bit key setup unsuccessful", key_size * 8);
key_size * 8); return -1;
return -1; }
}
traceEvent(TRACE_DEBUG, "setup_tf_key %u-bit key setup completed", key_size * 8);
traceEvent(TRACE_DEBUG, "setup_tf_key %u-bit key setup completed", return 0;
key_size * 8);
return 0;
} }
/* ****************************************************** */
static void transop_tick_tf(n2n_trans_op_t * arg, time_t now) { ; } static void transop_tick_tf (n2n_trans_op_t *arg, time_t now) {
// no tick action
}
/* ****************************************************** */
// Twofish initialization function // Twofish initialization function
int n2n_transop_tf_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { int n2n_transop_tf_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_tf_t *priv; transop_tf_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key; const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key); size_t encrypt_key_len = strlen(conf->encrypt_key);
memset(ttt, 0, sizeof(*ttt)); memset(ttt, 0, sizeof(*ttt));
ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH;
ttt->tick = transop_tick_tf; ttt->tick = transop_tick_tf;
ttt->deinit = transop_deinit_tf; ttt->deinit = transop_deinit_tf;
ttt->fwd = transop_encode_tf; ttt->fwd = transop_encode_tf;
ttt->rev = transop_decode_tf; ttt->rev = transop_decode_tf;
priv = (transop_tf_t*) calloc(1, sizeof(transop_tf_t)); priv = (transop_tf_t*)calloc(1, sizeof(transop_tf_t));
if(!priv) { if(!priv) {
traceEvent(TRACE_ERROR, "n2n_transop_tf_cbc_init cannot allocate transop_tf_t memory"); traceEvent(TRACE_ERROR, "n2n_transop_tf_cbc_init cannot allocate transop_tf_t memory");
return -1; return -1;
} }
ttt->priv = priv; ttt->priv = priv;
// setup the cipher and key // setup the cipher and key
return setup_tf_key(priv, encrypt_key, encrypt_key_len); return setup_tf_key(priv, encrypt_key, encrypt_key_len);
} }

Loading…
Cancel
Save