/* ------------------------------------------------------------------------- *
 *
 *   Program:   A C H T E R B A H N  (header file)
 *
 *              A new binary additive synchroneous stream cipher submitted 
 *              to the ECRYPT call for stream cipher primitives, profile 2.
 *              (80 bit key length, efficient for hardware applications)
 *
 *   Authors:   Berndt M. Gammel, Rainer Goettfert, Oliver Kniffler
 *
 *     Email:   berndt.gammel@infineon.com
 *              rainer.goettfert@infineon.com
 *              oliver.kniffler@infineon.com
 *
 *   Address:   Infineon Technologies AG
 *              St.-Martin-Str. 76
 *              D-81541 Munich
 *              Germany
 *
 *   Version:   1.0  (last change: Apr 18, 2005)
 *                
 *  Language:   ANSI C99
 *
 *   Sources:   achterbahn.c
 *                
 *  Includes:   ecrypt-sync.h, 
 *              ecrypt-portable.h, 
 *              ecrypt-config.h, 
 *              ecrypt-machine.h
 *                
 *  Makefile:   Makefile
 *
 * Platforms:   This program has been verified on the following platforms:
 *              gcc 3.4.3 on S.u.S.E. Linux 9.1
 *              gcc 3.3.2 on SunOS 5.7 / Solaris 2.7S
 *              gcc 3.3.2 on Redhat Linux 9.2
 *              gcc 3.3.1 on Cygwin (Windows 2000)
 *
 * Copyright:   (C) 2005 by Berndt M. Gammel, Rainer Goettfert, Oliver Kniffler,
 *              Infineon Technologies AG, St.-Martin-Str. 76, 
 *              D-81541 Munich, Germany.
 *              
 *              This software is free for commercial and non-commercial 
 *              use subject to the following conditions:
 *
 *              1.  Copyright remains vested in Infineon Technologies AG, 
 *              and Copyright notices in the code are not to be removed.  
 *              If this software is used in a product, Infineon Technologies AG
 *              should be given attribution as the author of the Achterbahn
 *              encryption algorithm. This can be in the form of a textual
 *              message at program startup or in documentation (online or
 *              textual) provided with the software.
 *
 *              2.  Redistribution and use in source and binary forms,
 *              with or without modification, are permitted provided that 
 *              the following conditions are met:
 *
 *              a. Redistributions of source code must retain the copyright notice,
 *                 this list of conditions and the following disclaimer.
 *
 *              b. Redistributions in binary form must reproduce the above
 *                 copyright notice, this list of conditions and the following 
 *                 disclaimer in the documentation and/or other materials provided 
 *                 with the distribution.
 *
 *              c. All advertising materials mentioning features or use of this
 *                 software must display the following acknowledgement:  This product
 *                 includes software developed by Infineon Technologies AG.
 *
 *              3.  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 *              WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *              MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND AGAINST
 *              INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
 *              CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *              EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *              PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *              PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *              LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *              NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *              SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *              4.  The license and distribution terms for any publically available
 *              version or derivative of this code cannot be changed, that is, 
 *              this code cannot simply be copied and put under another distribution 
 *              license including the GNU Public License.
 *             
 *              5.  A free and irrevocable license is hereby granted for the
 *              use of the Achterbahn encryption algorithm for any purpose. 
 *
 * ------------------------------------------------------------------------- */

#ifndef ECRYPT_SYNC
#define ECRYPT_SYNC

#include "ecrypt-portable.h"

/* ------------------------------------------------------------------------- */

/* Cipher parameters */

/* ------------------------------------------------------------------------- * 
 * The name of the cipher.
 * ------------------------------------------------------------------------- */

#define ECRYPT_NAME        "ACHTERBAHN" 
#define ECRYPT_PROFILE     "HW"

#define ECRYPT_AUTHORS     "B. M. Gammel, R. Goettfert, O. Kniffler" 
#define ECRYPT_AFFILIATION "Infineon Technologies AG" 
#define ECRYPT_ADDRESS     "St.-Martin-Str. 76, D-81541 Munich, Germany" 
#define ECRYPT_EMAIL       "{Berndt.Gammel,Rainer.Goettfert,Oliver.Kniffler}@infineon.com" 
#define ECRYPT_VERSION     "1.0" 

/* ------------------------------------------------------------------------- *
 * Specify which key and IV sizes are supported by your cipher. A user
 * should be able to enumerate the supported sizes by running the
 * following code:
 *
 * for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i)
 *   {
 *     keysize = ECRYPT_KEYSIZE(i);
 *
 *     ...
 *   }
 *
 * All sizes are in bits.
 * ------------------------------------------------------------------------- */

#define ECRYPT_MAXKEYSIZE 80U         /* constant keysize 80 bit */
#define ECRYPT_KEYSIZE(i) (80U+(i)*32)                

#define ECRYPT_MAXIVSIZE 64U          /* variable IV size */
#define ECRYPT_IVSIZE(i) ((i)*8)      /* 0, 8, 16, 24, 32, 40, 48, 56, 64 */

/* ------------------------------------------------------------------------- */

/* Data structures */

/* ------------------------------------------------------------------------- *
 * ECRYPT_ctx is the structure containing the representation of the
 * internal state of your cipher. 
 * ------------------------------------------------------------------------- */

typedef struct
{
  u32 A,B,C,D,E,F,G,H; /* state of 8 driving NLFSR in eight 32 bit words */
  u64 V;               /* state of configuration of output logics */

  u64 key0;            /* save key bits 0 to 63 in one double word */ 
  u32 ivsize;          /* save initialization vector size in bits */
  u32 iv_setup_done;   /* flag to mark that setup is done */
  u32 iv[64];          /* save 64 bit IV  - 1 bit/word for fast access */
  u32 ky[80];          /* save 80 bit key - 1 bit/word for fast access */
} ECRYPT_ctx;


/* Mandatory functions */

/* ------------------------------------------------------------------------- *
 * Key and message independent initialization. This function will be
 * called once when the program starts (e.g., to build expanded S-box
 * tables).
 * ------------------------------------------------------------------------- */

void ECRYPT_init();

/* ------------------------------------------------------------------------- *
 * Key setup. It is the user's responsibility to select the values of
 * keysize and ivsize from the set of supported values specified above.
 * ------------------------------------------------------------------------- */

void ECRYPT_keysetup(
  ECRYPT_ctx* ctx, 
  const u8* key, 
  u32 keysize,                /* Key size in bits. */ 
  u32 ivsize);                /* IV size in bits. */ 

/* ------------------------------------------------------------------------- *
 * IV setup. After having called ECRYPT_keysetup(), the user is
 * allowed to call ECRYPT_ivsetup() different times in order to
 * encrypt/decrypt different messages with the same key but different IV's.
 * ------------------------------------------------------------------------- */

void ECRYPT_ivsetup(
  ECRYPT_ctx* ctx, 
  const u8* iv);

/* ------------------------------------------------------------------------- *
 * Encryption/decryption of arbitrary length messages.
 *
 * For efficiency reasons, the API provides two types of
 * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function
 * (declared here) encrypts byte strings of arbitrary length, while
 * the ECRYPT_encrypt_blocks() function (defined later) only accepts
 * lengths which are multiples of ECRYPT_BLOCKLENGTH.
 * 
 * The user is allowed to make multiple calls to
 * ECRYPT_encrypt_blocks() to incrementally encrypt a long message,
 * but he is NOT allowed to make additional encryption calls once he
 * has called ECRYPT_encrypt_bytes() (unless he starts a new message
 * of course). For example, this sequence of calls is acceptable:
 *
 * ECRYPT_keysetup();
 *
 * ECRYPT_ivsetup();
 * ECRYPT_encrypt_blocks();
 * ECRYPT_encrypt_blocks();
 * ECRYPT_encrypt_bytes();
 *
 * ECRYPT_ivsetup();
 * ECRYPT_encrypt_blocks();
 * ECRYPT_encrypt_blocks();
 *
 * ECRYPT_ivsetup();
 * ECRYPT_encrypt_bytes();
 * 
 * The following sequence is not:
 *
 * ECRYPT_keysetup();
 * ECRYPT_ivsetup();
 * ECRYPT_encrypt_blocks();
 * ECRYPT_encrypt_bytes();
 * ECRYPT_encrypt_blocks();
 * ------------------------------------------------------------------------- */

void ECRYPT_encrypt_bytes(
  ECRYPT_ctx* ctx, 
  const u8* plaintext, 
  u8* ciphertext, 
  u32 msglen);                /* Message length in bytes. */ 

void ECRYPT_decrypt_bytes(
  ECRYPT_ctx* ctx, 
  const u8* ciphertext, 
  u8* plaintext, 
  u32 msglen);                /* Message length in bytes. */ 

/* ------------------------------------------------------------------------- */

/* Optional features */

/* ------------------------------------------------------------------------- *
 * For testing purposes it can sometimes be useful to have a function
 * which immediately generates keystream without having to provide it
 * with a zero plaintext. If your cipher cannot provide this function
 * (e.g., because it is not strictly a synchronous cipher), please
 * reset the ECRYPT_GENERATES_KEYSTREAM flag.
 * ------------------------------------------------------------------------- */

#define ECRYPT_GENERATES_KEYSTREAM
#ifdef ECRYPT_GENERATES_KEYSTREAM

void ECRYPT_keystream_bytes(
  ECRYPT_ctx* ctx,
  u8* keystream,
  u32 length);                /* Length of keystream in bytes. */

#endif

/* ------------------------------------------------------------------------- */

/* Optional optimizations */

/* ------------------------------------------------------------------------- * 
 * By default, the functions in this section are implemented using
 * calls to functions declared above. However, you might want to
 * implement them differently for performance reasons.
 * ------------------------------------------------------------------------- */

/* ------------------------------------------------------------------------- * 
 * All-in-one encryption/decryption of (short) packets.
 *
 * The default definitions of these functions can be found in
 * "ecrypt-sync.c". If you want to implement them differently, please
 * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag.
 * ------------------------------------------------------------------------- */

#define ECRYPT_USES_DEFAULT_ALL_IN_ONE 

void ECRYPT_encrypt_packet(
  ECRYPT_ctx* ctx, 
  const u8* iv,
  const u8* plaintext, 
  u8* ciphertext, 
  u32 msglen);

void ECRYPT_decrypt_packet(
  ECRYPT_ctx* ctx, 
  const u8* iv,
  const u8* ciphertext, 
  u8* plaintext, 
  u32 msglen);

/* ------------------------------------------------------------------------- * 
 * Encryption/decryption of blocks.
 * 
 * By default, these functions are defined as macros. If you want to
 * provide a different implementation, please undef the
 * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions
 * declared below.
 * ------------------------------------------------------------------------- */

#define ECRYPT_BLOCKLENGTH 4  

#define ECRYPT_USES_DEFAULT_BLOCK_MACROS 
#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS

#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks)  \
  ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext,                 \
    (blocks) * ECRYPT_BLOCKLENGTH)

#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks)  \
  ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext,                 \
    (blocks) * ECRYPT_BLOCKLENGTH)

#ifdef ECRYPT_GENERATES_KEYSTREAM

#define ECRYPT_keystream_blocks(ctx, keystream, blocks)            \
  ECRYPT_keystream_bytes(ctx, keystream,                        \
    (blocks) * ECRYPT_BLOCKLENGTH)

#endif

#else

void ECRYPT_encrypt_blocks(
  ECRYPT_ctx* ctx, 
  const u8* plaintext, 
  u8* ciphertext, 
  u32 blocks);                /* Message length in blocks. */ 

void ECRYPT_decrypt_blocks(
  ECRYPT_ctx* ctx, 
  const u8* ciphertext, 
  u8* plaintext, 
  u32 blocks);                /* Message length in blocks. */ 

#ifdef ECRYPT_GENERATES_KEYSTREAM

void ECRYPT_keystream_blocks(
  ECRYPT_ctx* ctx,
  const u8* keystream,
  u32 blocks);                /* Keystream length in blocks. */ 

#endif

#endif

/*
 * If your cipher can be implemented in different ways, you can use
 * the ECRYPT_VARIANT parameter to allow the user to choose between
 * them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please
 * only use this possibility if you really think it could make a
 * significant difference and keep the number of variants
 * (ECRYPT_MAXVARIANT) as small as possible (definitely not more than
 * 10). Note also that all variants should have exactly the same
 * external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.). 
 */
#define ECRYPT_MAXVARIANT 1                   /* [edit] */

#ifndef ECRYPT_VARIANT
#define ECRYPT_VARIANT 1
#endif

#if (ECRYPT_VARIANT > ECRYPT_MAXVARIANT)
#error this variant does not exist
#endif

/* ------------------------------------------------------------------------- */

#endif
