Commit e32dfe8a authored by Davide Galassi's avatar Davide Galassi

Merge branch 'feature/trivium_cipher' into 'master'

Trivium stream cipher

See merge request !4
parents 13da9bbc 08cb2557
Pipeline #37491513 passed with stages
in 1 minute and 12 seconds
/**
* @file trivium.h
* @brief Trivium stream cipher.
*
* Trivium is a synchronous stream cipher designed to provide a flexible
* trade-off between speed and gate count in hardware, and reasonably efficient
* software implementation.
*
* The cipher makes use of a 80-bit key and 80-bit initialisation vector (IV);
* its secret state has 288 bits, consisting of three interconnected non-linear
* feedback shift registers (NLFSR) of length 93, 84 and 111 bits, respectively.
*
* The cipher operation consists of two phases: the key and IV set-up and the
* keystream generation. Initialisation is very similar to keystream generation
* and requires 1152 steps of the clocking procedure of Trivium. The keystream
* is generated by repeatedly clocking the cipher, where in each clock cycle
* three state bits are updated using a non-linear feedback function, and one
* bit of keystream is produced and output. The cipher specification states
* that 264 keystream bits can be generated from each key/IV pair.
*
* For more information about refer to the eSTREAM project page:
* http://www.ecrypt.eu.org/stream/e2-trivium.html
*/
#ifndef CRY_TRIVIUM_H_
#define CRY_TRIVIUM_H_
#include <stddef.h>
#include <stdint.h>
#define CRY_TRIVIUM_KEYLEN 10 /* 80-bit */
#define CRY_TRIVIUM_IVLEN 10 /* 80-bit */
struct cry_trivium_ctx {
size_t keylen;
size_t ivlen;
uint8_t s[40];
uint8_t key[CRY_TRIVIUM_KEYLEN];
};
typedef struct cry_trivium_ctx cry_trivium_ctx;
#ifdef __cplusplus
extern "C"{
#endif
/**
* Context initialization.
*
* @param ctx Trivium context.
*/
void cry_trivium_init(cry_trivium_ctx *ctx);
/**
* Set the cipher key.
*
* @param ctx Trivium context.
* @param key Cipher key.
* @param size Cipher key size.
*/
void cry_trivium_key_set(cry_trivium_ctx *ctx, const unsigned char *key,
size_t size);
/**
* Set the initialization vector.
*
* @param ctx Trivium context.
* @param iv Initialization vector.
* @param size Initialization vector size.
*/
void cry_trivium_iv_set(cry_trivium_ctx *ctx, const unsigned char *iv,
size_t size);
/**
* Encryption function.
*
* @param ctx Trivium context.
* @param dst Destination buffer (ciphertext).
* @param src Source buffer (cleartext).
* @param size Number of bytes.
*/
void cry_trivium_encrypt(cry_trivium_ctx *ctx, unsigned char *dst,
const unsigned char *src, unsigned int size);
/**
* Decryption function.
*
* @param ctx Trivium context.
* @param dst Destination buffer (cleartext).
* @param src Source buffer (ciphertext).
* @param size Number of bytes.
*/
void cry_trivium_decrypt(cry_trivium_ctx *ctx, unsigned char *dst,
const unsigned char *src, unsigned int size);
#ifdef __cplusplus
}
#endif
#endif /* CRY_TRIVIUM_H_ */
......@@ -17,6 +17,7 @@ objs-y := version.o \
ecdh.o \
dsa.o \
ecdsa.o \
trivium.o \
misc.o
subdirs-y += mpi crc prng sum ecp classic
......
#include "cry/trivium.h"
#include <string.h>
#define U8C(v) (v##U)
#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
/* replace with CRY_READ32_LE */
#define U8TO32_LITTLE(p) \
(((uint32_t)((p)[0]) ) | \
((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | \
((uint32_t)((p)[3]) << 24))
/* replace with CRY_WRITE32_LE */
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define S(a, n) (s##a##n)
#define T(a) (t##a)
#define LOAD(s) do { \
S(1, 1) = U8TO32_LITTLE((s) + 0); \
S(1, 2) = U8TO32_LITTLE((s) + 4); \
S(1, 3) = U8TO32_LITTLE((s) + 8); \
S(2, 1) = U8TO32_LITTLE((s) + 12); \
S(2, 2) = U8TO32_LITTLE((s) + 16); \
S(2, 3) = U8TO32_LITTLE((s) + 20); \
S(3, 1) = U8TO32_LITTLE((s) + 24); \
S(3, 2) = U8TO32_LITTLE((s) + 28); \
S(3, 3) = U8TO32_LITTLE((s) + 32); \
S(3, 4) = U8TO32_LITTLE((s) + 36); \
} while (0)
#define STORE(s) do { \
U32TO8_LITTLE((s) + 0, S(1, 1)); \
U32TO8_LITTLE((s) + 4, S(1, 2)); \
U32TO8_LITTLE((s) + 8, S(1, 3)); \
U32TO8_LITTLE((s) + 12, S(2, 1)); \
U32TO8_LITTLE((s) + 16, S(2, 2)); \
U32TO8_LITTLE((s) + 20, S(2, 3)); \
U32TO8_LITTLE((s) + 24, S(3, 1)); \
U32TO8_LITTLE((s) + 28, S(3, 2)); \
U32TO8_LITTLE((s) + 32, S(3, 3)); \
U32TO8_LITTLE((s) + 36, S(3, 4)); \
} while (0)
#define S00(a, b) ((S(a, 1) << ( 32 - (b))))
#define S32(a, b) ((S(a, 2) << ( 64 - (b))) | (S(a, 1) >> ((b) - 32)))
#define S64(a, b) ((S(a, 3) << ( 96 - (b))) | (S(a, 2) >> ((b) - 64)))
#define S96(a, b) ((S(a, 4) << (128 - (b))) | (S(a, 3) >> ((b) - 96)))
#define UPDATE() do { \
T(1) = S64(1, 66) ^ S64(1, 93); \
T(2) = S64(2, 69) ^ S64(2, 84); \
T(3) = S64(3, 66) ^ S96(3, 111); \
Z(T(1) ^ T(2) ^ T(3)); \
T(1) ^= (S64(1, 91) & S64(1, 92)) ^ S64(2, 78); \
T(2) ^= (S64(2, 82) & S64(2, 83)) ^ S64(3, 87); \
T(3) ^= (S96(3, 109) & S96(3, 110)) ^ S64(1, 69); \
} while (0)
#define ROTATE() do { \
S(1, 3) = S(1, 2); \
S(1, 2) = S(1, 1); \
S(1, 1) = T(3); \
S(2, 3) = S(2, 2); \
S(2, 2) = S(2, 1); \
S(2, 1) = T(1); \
S(3, 4) = S(3, 3); \
S(3, 3) = S(3, 2); \
S(3, 2) = S(3, 1); \
S(3, 1) = T(2); \
} while (0)
void cry_trivium_init(cry_trivium_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
void cry_trivium_key_set(cry_trivium_ctx *ctx, const unsigned char *key,
size_t size)
{
size_t i;
ctx->keylen = (size <= CRY_TRIVIUM_KEYLEN) ? size : CRY_TRIVIUM_KEYLEN;
for (i = 0; i < ctx->keylen; i++)
ctx->key[i] = key[i];
for ( ; i < CRY_TRIVIUM_KEYLEN; i++)
ctx->key[i] = 0;
}
void cry_trivium_iv_set(cry_trivium_ctx *ctx, const unsigned char *iv,
size_t size)
{
size_t i;
uint32_t s11, s12, s13;
uint32_t s21, s22, s23;
uint32_t s31, s32, s33, s34;
uint32_t t1, t2, t3;
ctx->ivlen = (size <= CRY_TRIVIUM_IVLEN) ? size : CRY_TRIVIUM_IVLEN;
/*
* S initialized as:
* [ key || 0 ] || (96 bits)
* [ iv || 0 ] || (96 bits)
* [ 0 ... 0 || 0x70 || 0 ... 0 ] (128 bits)
*
* The last byte of the second FSR and the last two bytes of the
* third FSR are not used.
*/
for (i = 0; i < ctx->keylen; i++)
ctx->s[i] = ctx->key[i];
for ( ; i < 12; i++)
ctx->s[i] = 0;
for (i = 0; i < ctx->ivlen; i++)
ctx->s[12 + i] = iv[i];
for ( ; i < 12; i++)
ctx->s[12 + i] = 0;
for (i = 0; i < 13; i++)
ctx->s[24 + i] = 0;
ctx->s[24 + 13] = 0x70;
LOAD(ctx->s);
#define Z(w)
for (i = 0; i < 4 * 9; i++) {
UPDATE();
ROTATE();
}
STORE(ctx->s);
}
static void operate(cry_trivium_ctx *ctx, unsigned char *dst,
const unsigned char *src, unsigned int size)
{
size_t i;
uint32_t s11, s12, s13;
uint32_t s21, s22, s23;
uint32_t s31, s32, s33, s34;
uint32_t z;
uint32_t t1, t2, t3;
LOAD(ctx->s);
#undef Z
#define Z(w) U32TO8_LITTLE(dst + 4 * i, U8TO32_LITTLE(src + 4 * i) ^ w)
for (i = 0; i < size / 4; i++) {
UPDATE();
ROTATE();
}
#undef Z
#define Z(w) (z = w)
i *= 4;
if (i < size) {
UPDATE();
ROTATE();
for ( ; i < size; i++, z >>= 8)
dst[i] = src[i] ^ U8V(z);
}
STORE(ctx->s);
}
void cry_trivium_encrypt(cry_trivium_ctx *ctx, unsigned char *dst,
const unsigned char *src, unsigned int size)
{
operate(ctx, dst, src, size);
}
void cry_trivium_decrypt(cry_trivium_ctx *ctx, unsigned char *dst,
const unsigned char *src, unsigned int size)
{
operate(ctx, dst, src, size);
}
......@@ -15,6 +15,7 @@ objs := \
mpi_test.o \
hmac_test.o \
aes_test.o \
trivium_test.o \
hill_test.o \
affine_test.o
# gcm_test.o \
......
......@@ -6,6 +6,7 @@ void base64_test(void);
void mpi_test(void);
void hmac_test(void);
void aes_test(void);
void trivium_test(void);
void hill_test(void);
void affine_test(void);
......@@ -15,53 +16,65 @@ int g_fails;
int g_verbose;
unsigned char g_buf[BUFSIZ];
static const char *g_test_str[] = {
"version",
"memxor",
"base64",
"mpi",
"hmac",
"aes",
"hill",
"affine",
};
static char g_test_skip[ARLEN(g_test_str)];
struct sub_test {
const char *name;
test_func_t func;
};
static test_func_t g_test_func[] = {
version_test,
memxor_test,
base64_test,
mpi_test,
hmac_test,
aes_test,
hill_test,
affine_test,
#if 0
TEST_ELEM(cbc),
TEST_ELEM(ctr),
TEST_ELEM(gcm),
#define SUB_TEST(name) { #name , name ## _test }
struct sub_test g_tests[] = {
SUB_TEST(version),
#if 1
SUB_TEST(memxor),
SUB_TEST(base64),
SUB_TEST(mpi),
SUB_TEST(hmac),
SUB_TEST(aes),
SUB_TEST(trivium),
SUB_TEST(hill),
SUB_TEST(affine),
#endif
#if 0
TEST_ELEM(des),
TEST_ELEM(crc),
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(cmac),
TEST_ELEM(sum),
TEST_ELEM(rsa),
TEST_ELEM(rand),
TEST_ELEM(dh),
TEST_ELEM(dsa),
TEST_ELEM(ecp),
TEST_ELEM(ecdsa),
TEST_ELEM(ecdh),
TEST_ELEM(cbc),
TEST_ELEM(ctr),
TEST_ELEM(gcm),
TEST_ELEM(des),
TEST_ELEM(crc),
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(cmac),
TEST_ELEM(sum),
TEST_ELEM(rsa),
TEST_ELEM(rand),
TEST_ELEM(dh),
TEST_ELEM(dsa),
TEST_ELEM(ecp),
TEST_ELEM(ecdsa),
TEST_ELEM(ecdh),
TEST_ELEM(cbc),
TEST_ELEM(ctr),
TEST_ELEM(gcm),
TEST_ELEM(des),
TEST_ELEM(crc),
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(cmac),
TEST_ELEM(sum),
TEST_ELEM(rsa),
TEST_ELEM(rand),
TEST_ELEM(dh),
TEST_ELEM(dsa),
TEST_ELEM(ecp),
TEST_ELEM(ecdsa),
TEST_ELEM(ecdh),
#endif
};
#define NTESTS ARLEN(g_test_func)
#define NTESTS ARLEN(g_tests)
static char g_test_skip[NTESTS];
static int get_line(FILE *f, char *buf, size_t len)
......@@ -217,7 +230,7 @@ static void show_cases(void)
printf("\nTest cases:\n");
for (i = 0; i < NTESTS; i++)
printf(" %s\n", g_test_str[i]);
printf(" %s\n", g_tests[i].name);
printf("\n");
exit(0);
}
......@@ -244,7 +257,7 @@ static void parse_args(int argc, char *argv[])
memset(g_test_skip, 1, sizeof(g_test_skip));
do {
for (j = 0; j < NTESTS; j++) {
if (strcmp(argv[i], g_test_str[j]) == 0)
if (strcmp(argv[i], g_tests[j].name) == 0)
g_test_skip[j] = 0;
}
i++;
......@@ -268,7 +281,7 @@ int main(int argc, char *argv[])
for (i = 0; i < NTESTS; i++) {
if (g_test_skip[i] == 0)
g_test_func[i]();
g_tests[i].func();
}
printf("\n");
......
......@@ -64,7 +64,7 @@ void run(const char *name, void (* test)(void),
ASSERT_EQ((e), 0)
# define PRINT_HEX(msg, buf, siz) do { \
#define PRINT_HEX(msg, buf, siz) do { \
size_t __siz = siz; \
unsigned char *__p = buf; \
if (msg) printf("%s: ", msg); \
......@@ -72,10 +72,10 @@ void run(const char *name, void (* test)(void),
printf("\n"); \
} while(0)
# define PRINT_ASC(msg, buf, siz) \
#define PRINT_ASC(msg, buf, siz) \
printf("%s: %.*s\n", msg, (int)(siz), buf)
# define PRINT_MPI(msg, mpi, rad) do { \
#define PRINT_MPI(msg, mpi, rad) do { \
printf("%s:\t", msg); \
cry_mpi_print(mpi, rad); \
} while(0)
......
This diff is collapsed.
#include "test.h"
#include <cry/trivium.h>
struct trivium_param {
unsigned int keylen;
unsigned int ivlen;
unsigned int buflen;
unsigned char key[10];
unsigned char iv[10];
unsigned char buf[512];
};
static void param_init(struct trivium_param *par, int argc, char *argv[])
{
memset(par, 0, sizeof(*par));
par->keylen = raw_init(par->key, sizeof(par->key), argv[0]);
par->ivlen = raw_init(par->iv, sizeof(par->iv), argv[1]);
par->buflen = raw_init(par->buf, sizeof(par->buf), argv[2]);
}
static void trivium_operate(int argc, char *argv[])
{
cry_trivium_ctx ctx;
struct trivium_param par;
unsigned char src[512] = {0};
unsigned char dst[512];
unsigned char clr[512];
ASSERT(argc == 4);
param_init(&par, argc, argv);
cry_trivium_key_set(&ctx, par.key, par.keylen);
cry_trivium_iv_set(&ctx, par.iv, par.ivlen);
cry_trivium_encrypt(&ctx, dst, src, 512);
cry_trivium_key_set(&ctx, par.key, par.keylen);
cry_trivium_iv_set(&ctx, par.iv, par.ivlen);
cry_trivium_decrypt(&ctx, clr, dst, 512);
ASSERT_EQ_BUF(dst, par.buf, 512);
}
static void dispatch(int argc, char *argv[])
{
char *test = *argv;
argv++;
argc--;
if (strcmp(test, "trivium_operate") == 0)
trivium_operate(argc, argv);
else
printf("Test '%s' not defined\n", test);
}
void trivium_test(void)
{
printf("* TRIVIUM ECRYPT Vectors\n");
func_test("trivium_ecrypt.data", dispatch);
printf("\n");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment