Browse Source

Merge branch 'dev' into amndmntAes

pull/397/head
Logan oos Even 4 years ago
committed by GitHub
parent
commit
56071bf494
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      CMakeLists.txt
  2. 14
      doc/Crypto.md
  3. 7
      include/n2n.h
  4. 3
      include/n2n_define.h
  5. 44
      include/random_numbers.h
  6. 47
      include/speck.h
  7. 3
      include/tf.h
  8. 20
      src/random_numbers.c
  9. 1
      src/sn_utils.c
  10. 194
      src/speck.c
  11. 10
      src/tf.c
  12. 92
      src/transform_speck.c
  13. 19
      src/transform_tf.c

4
CMakeLists.txt

@ -4,7 +4,7 @@ include(CheckFunctionExists)
SET(CMAKE_VERBOSE_MAKEFILE ON)
# N2n release information
set(N2N_VERSION "2.7.0")
set(N2N_VERSION "2.9.0")
set(N2N_OSNAME ${CMAKE_SYSTEM})
execute_process(
COMMAND git --version
@ -29,7 +29,7 @@ MESSAGE(STATUS "Build from git rev: ${N2N_VERSION}")
endif (GIT_EXIST)
add_definitions(-DCMAKE_BUILD)
add_definitions(-DGIT_RELEASE="" -DPACKAGE_VERSION="${N2N_VERSION}" -DPACKAGE_OSNAME="${N2N_OSNAME}")
add_definitions(-DGIT_RELEASE="${N2N_VERSION}" -DPACKAGE_VERSION="${N2N_VERSION}" -DPACKAGE_OSNAME="${N2N_OSNAME}")
add_definitions(-DN2N_VERSION="${N2N_VERSION}" -DN2N_OSNAME="${N2N_OSNAME}")

14
doc/Crypto.md

@ -17,7 +17,7 @@ The following chart might help to make a quick comparison and decide what cipher
| Cipher | Mode | Block Size | Key Size | IV length |Speed | Built-In | Origin |
| :---: | :---:| :---: | :---: | :---: |:---: | :---: | --- |
|Twofish | CTS | 128 bits | 256 bit | 32 bit | - | Y | Bruce Schneier |
|Twofish | CTS | 128 bits | 256 bit | 128 bit | -..O | Y | Bruce Schneier |
|AES | CBC | 128 bits | 128, 192, 256 bit| 128 bit | O..+ | N | Joan Daemen, Vincent Rijmen, NSA-approved |
|ChaCha20| CTR | Stream | 256 bit | 128 bit | +..++| N | Daniel J. Bernstein |
|SPECK | CTR | Stream | 256 bit | 128 bit | ++ | Y | NSA |
@ -28,13 +28,11 @@ Note that AES and ChaCha20 are available only if n2n is compiled with openSSL su
### Twofish
This implementation prepends a 32 bit random value to the plain text. In the `src/transform_tf.c` file, it is called `nonce`. In CBC mode, this basically has the same effect as a respectively shorter IV.
This implementation prepends a 128 bit random value to the plain text. Its size is adjustable by changing the `TF_PREAMBLE_SIZE` definition found in `src/transform_tf.c`. It defaults to TF_BLOCK_SIZE (== 16). As CTS uses underlying CBC mode, this basically has the same effect as a respectively shorter IV.
Twofish requires no padding as it employs a CBC/CTS scheme which can send out plaintext-length ciphertexts. The scheme however has a small flaw in handling messages shorter than one block, only low-level programmer might encounter this.
Twofish is the slowest of the ciphers present.
_We might try to find a faster implementation._
On Intel CPUs, Twofish usually is the slowest of the ciphers present. However, on Raspberry Pi 3B+, Twofish was observed to be faster than AES-CTS. Your mileage may vary. Cipher speed's can be compared running the `tools/n2n-benchmark` tool.
### AES
@ -42,8 +40,6 @@ AES also prepends a random value to the plaintext. Its size is adjustable by cha
AES relies on openSSL's `evp_*` interface which also offers hardware acceleration where available (SSE, AES-NI, …). It however is slower than the following stream ciphers because the CBC mode cannot compete with the optimized stream ciphers.
_Perhaps, AES-CTR being a stream cipher could have competed with the stream ciphers._
### ChaCha20
ChaCha20 was the first stream cipher supported by n2n.
@ -52,13 +48,13 @@ It also relies on openSSL's `evp_*` interface. It does not use the Poly1305 mess
The random full 128-bit IV is transmitted in plain.
ChaCha20 usually performs faster than AES-CBC.
ChaCha20 usually performs faster than AES-CTS.
### SPECK
SPECK is recommended by the NSA for offical use in case AES implementation is not feasible due to system constraints (performance, size, …). The block cipher is used in CTR mode making it a stream cipher. The random full 128-bit IV is transmitted in plain.
On Intel CPUs, SPECK performs even faster than openSSL's ChaCha20 as it takes advantage of SSE4 or AVX2 if available (compile using `-march=native`). On Raspberry's ARM CPU, it is second place behind ChaCha20 and before AES-CBC.
On Intel CPUs, SPECK performs even faster than openSSL's ChaCha20 as it takes advantage of SSE4 or AVX2 if available (compile using `-march=native`). On Raspberry's ARM CPU, it is second place behind ChaCha20 and before Twofish.
### Random Numbers

7
include/n2n.h

@ -83,14 +83,12 @@
#define N2N_CAN_NAME_IFACE 1
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define GRND_NONBLOCK 1
#endif /* #ifdef __linux__ */
#ifdef __FreeBSD__
@ -100,10 +98,6 @@
#include <syslog.h>
#include <sys/wait.h>
#if defined (__RDRND__) || defined (__RDSEED__)
#include <immintrin.h>
#endif
#define ETH_ADDR_LEN 6
struct ether_hdr
@ -135,7 +129,6 @@ typedef struct ether_hdr ether_hdr_t;
#include <openssl/crypto.h>
#endif
#define closesocket(a) close(a)
#endif /* #ifndef WIN32 */

3
include/n2n_define.h

@ -51,9 +51,6 @@
#define TIME_STAMP_JITTER 0x0000000027100000LL /* we allow a packet to arrive 160 ms (== 0x27100 us) before another
* set to 0x0000000000000000LL if increasing (or equal) time stamps allowed only */
/* parameter for random number generation */
#define RND_RETRIES 1000 /* syscall and inquiring random number from hardware generators might fail, so we will retry */
/* N2N compression indicators. */
/* Compression is disabled by default for outgoing packets if no cli
* option is given. All edges are built with decompression support so

44
include/random_numbers.h

@ -16,19 +16,46 @@
*
*/
/* The WIN32 code is still untested and thus commented
#ifndef RND_H
#define RND_H
#include <stdint.h>
#include <stddef.h>
#include <time.h> // time, clock
#include "n2n.h" // traceEvent
// syscall and inquiring random number from hardware generators might fail, so we will retry
#define RND_RETRIES 1000
#if defined (__linux__)
#include <sys/syscall.h> // syscall, SYS_getrandom
#ifdef SYS_getrandom
#define GRND_NONBLOCK 1
#include <errno.h> // errno, EAGAIN
#endif
#endif
#if defined (__RDRND__) || defined (__RDSEED__)
#include <immintrin.h> // _rdrand64_step, rdseed4_step
#endif
/* The WIN32 code is still untested and thus commented, also see random_numbers.c
#if defined (WIN32)
#include <Wincrypt.h>
#endif
#include <Wincrypt.h> // HCTYPTPROV, Crypt*-functions
#endif
*/
struct rn_generator_state_t {
typedef struct rn_generator_state_t {
uint64_t a, b;
};
} rn_generator_state_t;
struct splitmix64_state_t {
typedef struct splitmix64_state_t {
uint64_t s;
};
} splitmix64_state_t;
int n2n_srand (uint64_t seed);
@ -36,3 +63,6 @@ int n2n_srand (uint64_t seed);
uint64_t n2n_rand ();
uint64_t n2n_seed ();
#endif // RND_H

47
include/speck.h

@ -1,3 +1,22 @@
/**
* (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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not see see <http://www.gnu.org/licenses/>
*
*/
// cipher SPECK -- 128 bit block size -- 256 bit key size
// taken from (and modified: removed pure crypto-stream generation and seperated key expansion)
// https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/
@ -7,13 +26,20 @@
#define SPECK_H
#include <stdint.h>
#include <stdlib.h>
#include "portable_endian.h"
#define u32 uint32_t
#define u64 uint64_t
#define N2N_SPECK_IVEC_SIZE 16
#define SPECK_KEY_BYTES (256/8)
#if defined (__AVX2__)
#define SPECK_ALIGNED_CTX 32
#include <immintrin.h>
#define SPECK_ALIGNED_CTX 32
#define u256 __m256i
typedef struct {
u256 rk[34];
@ -22,9 +48,9 @@ typedef struct {
#elif defined (__SSE4_2__)
#include <immintrin.h>
#define SPECK_ALIGNED_CTX 16
#define SPECK_CTX_BYVAL 1
#include <immintrin.h>
#define u128 __m128i
typedef struct {
u128 rk[34];
@ -48,33 +74,30 @@ typedef struct {
#endif
// -----
int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n,
#if defined (SPECK_CTX_BYVAL)
speck_context_t ctx);
#else
speck_context_t *ctx);
#endif
speck_context_t *ctx);
int speck_init (const unsigned char *k, speck_context_t **ctx);
int speck_expand_key (const unsigned char *k, speck_context_t *ctx);
int speck_deinit (speck_context_t *ctx);
// -----
int speck_he (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx);
int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx);
// -----
int speck_he_iv_encrypt (unsigned char *inout, speck_context_t *ctx);
int speck_he_iv_decrypt (unsigned char *inout, speck_context_t *ctx);
int speck_expand_key_he_iv (const unsigned char *k, speck_context_t *ctx);
#endif
#endif // SPECK_H

3
include/tf.h

@ -53,6 +53,7 @@ THE SOFTWARE.
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "portable_endian.h"
#define TF_BLOCK_SIZE 16
@ -78,5 +79,7 @@ int tf_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len,
int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx);
int tf_deinit (tf_context_t *ctx);
#endif // TF_H

20
src/random_numbers.c

@ -16,11 +16,8 @@
*
*/
#ifdef SYS_getrandom
#include <errno.h>
#endif
#include "n2n.h"
#include "random_numbers.h"
/* The following code offers an alterate pseudo random number generator
@ -31,13 +28,13 @@
/* The state must be seeded in a way that it is not all zero, choose some
arbitrary defaults (in this case: taken from splitmix64) */
static struct rn_generator_state_t rn_current_state = {
static rn_generator_state_t rn_current_state = {
.a = 0x9E3779B97F4A7C15,
.b = 0xBF58476D1CE4E5B9 };
/* used for mixing the initializing seed */
static uint64_t splitmix64 (struct splitmix64_state_t *state) {
static uint64_t splitmix64 (splitmix64_state_t *state) {
uint64_t result = state->s;
@ -51,8 +48,9 @@ static uint64_t splitmix64 (struct splitmix64_state_t *state) {
int n2n_srand (uint64_t seed) {
uint8_t i;
struct splitmix64_state_t smstate = {seed};
splitmix64_state_t smstate = {seed};
rn_current_state.a = 0;
rn_current_state.b = 0;
@ -67,7 +65,7 @@ int n2n_srand (uint64_t seed) {
rn_current_state.b = 0xBF58476D1CE4E5B9;
}
/* stabilize in unlikely case of weak state with only a few bits set */
// stabilize in unlikely case of weak state with only a few bits set
for(i = 0; i < 32; i++)
n2n_rand();
@ -160,16 +158,16 @@ uint64_t n2n_seed (void) {
#ifdef WIN32
HCRYPTPROV crypto_provider;
CryptAcquireContext (&crypto_provider, NULL, (LPCWSTR)L"Microsoft Base Cryptographic Provider v1.0",
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptGenRandom (crypto_provider, 8, &seed);
CryptReleaseContext (crypto_provider, 0);
ret += seed;
#endif */
seed = time(NULL); /* UTC in seconds */
seed = time(NULL); // UTC in seconds
ret += seed;
seed = clock() * 18444244737; /* clock() = ticks since program start */
seed = clock() * 18444244737; // clock() = ticks since program start
ret += seed;
return ret;

1
src/sn_utils.c

@ -997,6 +997,7 @@ static int process_udp(n2n_sn_t * sss,
memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t));
if ((reg.dev_addr.net_addr == 0) || (reg.dev_addr.net_addr == 0xFFFFFFFF) || (reg.dev_addr.net_bitlen == 0) ||
((reg.dev_addr.net_addr & 0xFFFF0000) == 0xA9FE0000 /* 169.254.0.0 */)) {
memset(&ipaddr, 0, sizeof(n2n_ip_subnet_t));
assign_one_ip_addr(comm, &ipaddr);
ack.dev_addr.net_addr = ipaddr.net_addr;
ack.dev_addr.net_bitlen = ipaddr.net_bitlen;

194
src/speck.c

@ -1,9 +1,26 @@
/**
* (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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not see see <http://www.gnu.org/licenses/>
*
*/
// cipher SPECK -- 128 bit block size -- 256 bit key size -- CTR mode
// taken from (and modified: removed pure crypto-stream generation and seperated key expansion)
// https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/
#include <stdlib.h>
#include "portable_endian.h"
#include "speck.h"
@ -139,8 +156,8 @@ static int speck_encrypt_xor(unsigned char *out, const unsigned char *in, u64 no
}
int speck_ctr( unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
static int internal_speck_ctr(unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
int i;
u64 nonce[2];
@ -195,10 +212,11 @@ int speck_ctr( unsigned char *out, const unsigned char *in, unsigned long long i
}
int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
static int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
u64 K[4];
size_t i;
for (i = 0; i < numkeywords; i++)
K[i] = ((u64 *)k)[i];
@ -281,6 +299,7 @@ int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
RK(C,A,k,key,28), RK(D,A,k,key,29), RK(B,A,k,key,30), RK(C,A,k,key,31), RK(D,A,k,key,32), RK(B,A,k,key,33))
// attention: ctx is provided by value as it is faster in this case, astonishingly
static int speck_encrypt_xor (unsigned char *out, const unsigned char *in, u64 nonce[], const speck_context_t ctx, int numbytes) {
u64 x[2], y[2];
@ -325,9 +344,9 @@ static int speck_encrypt_xor (unsigned char *out, const unsigned char *in, u64 n
return 0;
}
int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, const speck_context_t ctx) {
// attention: ctx is provided by value as it is faster in this case, astonishingly
static int internal_speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, const speck_context_t ctx) {
int i;
u64 nonce[2];
@ -377,10 +396,11 @@ int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long i
}
int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
static int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
u64 K[4];
size_t i;
for (i = 0; i < numkeywords; i++)
K[i] = ((u64 *)k)[i];
@ -497,8 +517,8 @@ static int speck_encrypt_xor (unsigned char *out, const unsigned char *in, u64 n
}
int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
static int internal_speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
int i;
u64 nonce[2];
@ -548,10 +568,11 @@ int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long i
}
int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
static int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
u64 K[4];
size_t i;
for (i = 0; i < numkeywords; i++)
K[i] = ((u64 *)k)[i];
@ -582,8 +603,8 @@ static int speck_encrypt (u64 *u, u64 *v, speck_context_t *ctx) {
}
int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
static int internal_speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
u64 i, nonce[2], x, y, t;
unsigned char *block = malloc (16);
@ -617,7 +638,7 @@ int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long i
}
int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
static int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
u64 K[4];
u64 i;
@ -638,12 +659,57 @@ int speck_expand_key (const unsigned char *k, speck_context_t *ctx) {
}
#endif // AVX, SSE, NEON, plain C ------------------------------------------------
#endif // AVX, SSE, NEON, plain C
// this functions wraps the call to internal speck_ctr functions which have slightly different
// signature -- ctx by value for SSE with SPECK_CTX_BYVAL defined in speck.h, by name otherwise
inline int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen,
const unsigned char *n, speck_context_t *ctx) {
return internal_speck_ctr (out, in, inlen, n,
#if defined (SPECK_CTX_BYVAL)
*ctx);
#else
ctx);
#endif
}
int speck_init (const unsigned char *k, speck_context_t **ctx) {
#if defined (SPECK_ALIGNED_CTX)
*ctx = (speck_context_t*) _mm_malloc (sizeof(speck_context_t), SPECK_ALIGNED_CTX);
#else
*ctx = (speck_context_t*) calloc (1, sizeof(speck_context_t));
#endif
if(!(*ctx)) {
return -1;
}
return speck_expand_key(k, *ctx);
}
int speck_deinit (speck_context_t *ctx) {
if(ctx) {
#if defined (SPECK_ALIGNED_CTX)
_mm_free (ctx);
#else
free (ctx);
#endif
}
return 0;
}
// ----------------------------------------------------------------------------------------
// cipher SPECK -- 128 bit block size -- 128 bit key size -- CTR mode
// used for header encryption, thus the prefix 'he_'
// for now: just plain C -- AVX, SSE, NEON might follow
// for now: just plain C -- AVX, SSE, NEON do not make sense for short header
#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r))))
#define ROL64(x,r) (((x)<<(r))|((x)>>(64-(r))))
@ -787,97 +853,3 @@ int speck_expand_key_he_iv (const unsigned char *k, speck_context_t *ctx) {
return 1;
}
// ----------------------------------------------------------------------------------------
/*
// code for testing -- to be removed when finished
#include <stdio.h> // for testing
#include <string.h>
int speck_test () {
uint8_t key[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
uint8_t k96[12] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D };
uint8_t iv[16] = { 0x70, 0x6f, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x20,
0x49, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65 };
uint8_t xv[16] = { 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x74,
0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c };
uint8_t p96[12] = { 0x20, 0x75, 0x73, 0x61, 0x67, 0x65,
0x2C, 0x20, 0x68, 0x6F, 0x77, 0x65 };
uint8_t pt[16] = { 0x00 };
// expected outcome (according to pp. 35 & 36 of Implementation Guide 1.1 as of 2019) and
// original cipher presentation as of 2013 in which notably a different endianess is used
uint8_t ct[16] = { 0x43, 0x8f, 0x18, 0x9c, 0x8d, 0xb4, 0xee, 0x4e,
0x3e, 0xf5, 0xc0, 0x05, 0x04, 0x01, 0x09, 0x41 };
uint8_t xt[16] = { 0x18, 0x0d, 0x57, 0x5c, 0xdf, 0xfe, 0x60, 0x78,
0x65, 0x32, 0x78, 0x79, 0x51, 0x98, 0x5d, 0xa6 };
uint8_t x96[12] = { 0xAA, 0x79, 0x8F, 0xDE, 0xBD, 0x62,
0x78, 0x71, 0xAB, 0x09, 0x4D, 0x9E };
speck_context_t ctx;
speck_expand_key (key, &ctx);
#if defined (SPECK_CTX_BYVAL)
speck_ctr (pt, pt, 16, iv, ctx);
#else
speck_ctr (pt, pt, 16, iv, &ctx);
#endif
u64 i;
fprintf (stderr, "rk00: %016llx\n", ctx.key[0]);
fprintf (stderr, "rk33: %016llx\n", ctx.key[33]);
fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt);
fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n");
int ret = 1;
for (i=0; i < 16; i++)
if (pt[i] != ct[i]) ret = 0;
memset (pt, 0, 16);
speck_expand_key_he (key, &ctx);
speck_he (pt, pt, 16, xv, &ctx);
fprintf (stderr, "rk00: %016llx\n", ctx.key[0]);
fprintf (stderr, "rk31: %016llx\n", ctx.key[31]);
fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt);
fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n");
for (i=0; i < 16; i++)
if (pt[i] != xt[i]) ret = 0;
speck_expand_key_he_iv (k96, &ctx);
speck_he_iv_encrypt (p96, &ctx);
// speck_he_iv_decrypt (p96, &ctx);
// speck_he_iv_encrypt (p96, &ctx);
fprintf (stderr, "rk00: %016llx\n", ctx.key[0]);
fprintf (stderr, "rk27: %016llx\n", ctx.key[27]);
fprintf (stderr, "out : %016lx\n", *(uint64_t*)p96);
fprintf (stderr, "mem : " ); for (i=0; i < 12; i++) fprintf (stderr, "%02x ", p96[i]); fprintf (stderr, "\n");
for (i=0; i < 12; i++)
if (p96[i] != x96[i]) ret = 0;
return (ret);
}
int main (int argc, char* argv[]) {
fprintf (stdout, "SPECK SELF TEST RESULT: %u\n", speck_test (0,NULL));
}
*/

10
src/tf.c

@ -48,7 +48,7 @@ THE SOFTWARE.
#include "tf.h"
#include "portable_endian.h"
const uint8_t RS[4][8] = { { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, },
{ 0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5, },
@ -503,3 +503,11 @@ int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx) {
return 0;
}
int tf_deinit (tf_context_t *ctx) {
if (ctx) free (ctx);
return 0;
}

92
src/transform_speck.c

@ -16,19 +16,16 @@
*
*/
#include "n2n.h"
#define N2N_SPECK_IVEC_SIZE 16
#include "n2n.h"
#define SPECK_KEY_BYTES (256/8)
/* Speck plaintext preamble */
#define TRANSOP_SPECK_PREAMBLE_SIZE (N2N_SPECK_IVEC_SIZE)
#define TRANSOP_SPECK_PREAMBLE_SIZE (N2N_SPECK_IVEC_SIZE)
typedef unsigned char n2n_speck_ivec_t[N2N_SPECK_IVEC_SIZE];
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;
/* ****************************************************** */
@ -36,26 +33,11 @@ typedef struct transop_speck {
static int transop_deinit_speck(n2n_trans_op_t *arg) {
transop_speck_t *priv = (transop_speck_t *)arg->priv;
if(priv)
#if defined (SPECK_ALIGNED_CTX)
_mm_free (priv);
#else
free (priv);
#endif
return 0;
}
if(priv->ctx) speck_deinit(priv->ctx);
/* ****************************************************** */
if(priv) free (priv);
static void set_speck_iv(transop_speck_t *priv, n2n_speck_ivec_t ivec) {
// keep in mind the following condition: N2N_SPECK_IVEC_SIZE % sizeof(rand_value) == 0 !
uint64_t rand_value;
uint8_t i;
for (i = 0; i < N2N_SPECK_IVEC_SIZE; i += sizeof(rand_value)) {
rand_value = n2n_rand();
memcpy(ivec + i, &rand_value, sizeof(rand_value));
}
return 0;
}
/* ****************************************************** */
@ -74,31 +56,30 @@ static int transop_encode_speck(n2n_trans_op_t * arg,
const uint8_t * inbuf,
size_t in_len,
const uint8_t * peer_mac) {
int len=-1;
transop_speck_t * priv = (transop_speck_t *)arg->priv;
if(in_len <= N2N_PKT_BUF_SIZE) {
if((in_len + TRANSOP_SPECK_PREAMBLE_SIZE) <= out_len) {
size_t idx=0;
n2n_speck_ivec_t enc_ivec = {0};
traceEvent(TRACE_DEBUG, "encode_speck %lu bytes", in_len);
/* Generate and encode the IV. */
set_speck_iv(priv, enc_ivec);
encode_buf(outbuf, &idx, &enc_ivec, N2N_SPECK_IVEC_SIZE);
encode_uint64(outbuf, &idx, n2n_rand());
encode_uint64(outbuf, &idx, n2n_rand());
/* Encrypt the payload and write the ciphertext after the iv. */
/* 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;
speck_ctr (outbuf + TRANSOP_SPECK_PREAMBLE_SIZE, // output starts right after the iv
inbuf, // input
in_len, // len
outbuf, // iv (already encoded in outbuf, speck does not change it)
priv->ctx); // ctx already setup with round keys
speck_ctr (outbuf + TRANSOP_SPECK_PREAMBLE_SIZE, inbuf, in_len, enc_ivec,
#if defined (SPECK_CTX_BYVAL)
(priv->ctx));
#else
&(priv->ctx));
#endif
traceEvent(TRACE_DEBUG, "encode_speck: encrypted %u bytes.\n", in_len);
len += TRANSOP_SPECK_PREAMBLE_SIZE; /* size of data carried in UDP. */
@ -119,6 +100,7 @@ static int transop_decode_speck(n2n_trans_op_t * arg,
const uint8_t * inbuf,
size_t in_len,
const uint8_t * peer_mac) {
int len=0;
transop_speck_t * priv = (transop_speck_t *)arg->priv;
@ -128,21 +110,17 @@ static int transop_decode_speck(n2n_trans_op_t * arg,
{
size_t rem=in_len;
size_t idx=0;
n2n_speck_ivec_t dec_ivec = {0};
traceEvent(TRACE_DEBUG, "decode_speck %lu bytes", in_len);
len = (in_len - TRANSOP_SPECK_PREAMBLE_SIZE);
/* Get the IV */
decode_buf((uint8_t *)&dec_ivec, N2N_SPECK_IVEC_SIZE, inbuf, &rem, &idx);
len = (in_len - TRANSOP_SPECK_PREAMBLE_SIZE);
speck_ctr (outbuf, // output
inbuf + TRANSOP_SPECK_PREAMBLE_SIZE, // encrypted data starts right after preamble (IV)
len, // len
inbuf, // IV can be found at input's beginning
priv->ctx); // ctx already setup with round keys
speck_ctr (outbuf, inbuf + TRANSOP_SPECK_PREAMBLE_SIZE, len, dec_ivec,
#if defined (SPECK_CTX_BYVAL)
(priv->ctx));
#else
&(priv->ctx));
#endif
traceEvent(TRACE_DEBUG, "decode_speck: decrypted %u bytes.\n", len);
traceEvent(TRACE_DEBUG, "decode_speck decrypted %u bytes.\n", len);
} else
traceEvent(TRACE_ERROR, "decode_speck inbuf wrong size (%ul) to decrypt.", in_len);
@ -154,20 +132,17 @@ static int transop_decode_speck(n2n_trans_op_t * arg,
static int setup_speck_key(transop_speck_t *priv, const uint8_t *key, ssize_t key_size) {
uint8_t key_mat_buf[32] = { 0x00 };
/* Clear out any old possibly longer key matter. */
memset(&(priv->ctx), 0, sizeof(speck_context_t) );
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 */
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) */
speck_expand_key (key_mat_buf, &(priv->ctx));
speck_init(key_mat_buf, &(priv->ctx));
traceEvent(TRACE_DEBUG, "Speck key setup completed\n");
traceEvent(TRACE_DEBUG, "setup_speck_key completed\n");
return(0);
return 0;
}
/* ****************************************************** */
@ -175,8 +150,10 @@ static int setup_speck_key(transop_speck_t *priv, const uint8_t *key, ssize_t ke
static void transop_tick_speck(n2n_trans_op_t * arg, time_t now) { ; }
/* ****************************************************** */
/* Speck initialization function */
int n2n_transop_speck_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_speck_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key);
@ -188,17 +165,14 @@ int n2n_transop_speck_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
ttt->deinit = transop_deinit_speck;
ttt->fwd = transop_encode_speck;
ttt->rev = transop_decode_speck;
#if defined (SPECK_ALIGNED_CTX)
priv = (transop_speck_t*) _mm_malloc (sizeof(transop_speck_t), SPECK_ALIGNED_CTX);
#else
priv = (transop_speck_t*) calloc (1, sizeof(transop_speck_t));
#endif
priv = (transop_speck_t*) calloc(1, sizeof(transop_speck_t));
if(!priv) {
traceEvent(TRACE_ERROR, "cannot allocate transop_speck_t memory");
traceEvent(TRACE_ERROR, "n2n_transop_speck_init cannot allocate transop_speck_t memory");
return(-1);
}
ttt->priv = priv;
/* 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);
}

19
src/transform_tf.c

@ -40,7 +40,7 @@ typedef struct transop_tf {
static int transop_deinit_tf(n2n_trans_op_t *arg) {
transop_tf_t *priv = (transop_tf_t *)arg->priv;
if(priv->ctx) free(priv->ctx);
if(priv->ctx) tf_deinit(priv->ctx);
if(priv) free(priv);
@ -81,12 +81,8 @@ static int transop_encode_tf(n2n_trans_op_t * arg,
traceEvent(TRACE_DEBUG, "transop_encode_tf %lu bytes plaintext", in_len);
// full block sized random value (128 bit)
// !!! replace with 2 calls to encode_uint64(...) as as available
// !!! which is still under consideration in pull request 'revAes'
encode_uint32(assembly, &idx, n2n_rand());
encode_uint32(assembly, &idx, n2n_rand());
encode_uint32(assembly, &idx, n2n_rand());
encode_uint32(assembly, &idx, n2n_rand());
encode_uint64(assembly, &idx, n2n_rand());
encode_uint64(assembly, &idx, n2n_rand());
// adjust for maybe differently chosen TF_PREAMBLE_SIZE
idx = TF_PREAMBLE_SIZE;
@ -159,7 +155,7 @@ static int transop_decode_tf(n2n_trans_op_t * arg,
tf_cbc_decrypt(assembly, assembly, in_len + TF_BLOCK_SIZE - rest, tf_null_iv, priv->ctx);
// check for expected zero padding and give a warning otherwise
if (memcmp(assembly + in_len, tf_null_iv, TF_BLOCK_SIZE - rest)) {
if(memcmp(assembly + in_len, tf_null_iv, TF_BLOCK_SIZE - rest)) {
traceEvent(TRACE_WARNING, "transop_decode_tf payload decryption failed with unexpected cipher text stealing padding");
return -1;
}
@ -191,7 +187,7 @@ static int setup_tf_key(transop_tf_t *priv, const uint8_t *password, ssize_t pas
key_size = 32; // 256 bit
// 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",
key_size * 8);
return -1;
@ -210,6 +206,7 @@ static void transop_tick_tf(n2n_trans_op_t * arg, time_t now) { ; }
// Twofish initialization function
int n2n_transop_tf_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
transop_tf_t *priv;
const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
size_t encrypt_key_len = strlen(conf->encrypt_key);
@ -225,10 +222,10 @@ int n2n_transop_tf_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
priv = (transop_tf_t*) calloc(1, sizeof(transop_tf_t));
if(!priv) {
traceEvent(TRACE_ERROR, "n2n_transop_tf_cbc_init cannot allocate transop_tf_t memory");
return(-1);
return -1;
}
ttt->priv = priv;
// 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