Commit 77d4406d authored by Davide Galassi's avatar Davide Galassi

Trivium stream cipher first implementation

parent 13da9bbc
Pipeline #36485295 passed with stages
in 1 minute and 30 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 (LFSR) 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;
ctx->ivlen = (size <= CRY_TRIVIUM_IVLEN) ? size : CRY_TRIVIUM_IVLEN;
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++) {
uint32_t t1, t2, t3;
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;
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++) {
uint32_t t1, t2, t3;
UPDATE();
ROTATE();
}
#undef Z
#define Z(w) (z = w)
i *= 4;
if (i < size) {
uint32_t t1, t2, t3;
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);
}
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