Main Page Modules Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# Aes.h

Go to the documentation of this file.

    00001 /* aes.h */
    00002
    00003 /* ---------- See examples at end of this file for typical usage -------- */
    00004
    00005 /* AES Cipher header file for ANSI C Submissions
    00006     Lawrence E. Bassham III
    00007     Computer Security Division
    00008     National Institute of Standards and Technology
    00009
    00010     This sample is to assist implementers developing to the
    00011 Cryptographic API Profile for AES Candidate Algorithm Submissions.
    00012 Please consult this document as a cross-reference.
    00013
    00014     ANY CHANGES, WHERE APPROPRIATE, TO INFORMATION PROVIDED IN THIS FILE
    00015 MUST BE DOCUMENTED. CHANGES ARE ONLY APPROPRIATE WHERE SPECIFIED WITH
    00016 THE STRING "CHANGE POSSIBLE". FUNCTION CALLS AND THEIR PARAMETERS
    00017 CANNOT BE CHANGED. STRUCTURES CAN BE ALTERED TO ALLOW IMPLEMENTERS TO
    00018 INCLUDE IMPLEMENTATION SPECIFIC INFORMATION.
    00019 */
    00020
    00021 /* Includes:
    00022     Standard include files
    00023 */
    00024
    00025 #include    <stdio.h>
    00026 #include    "platform.h"            /* platform-specific defines */
    00027
    00028 /*  Defines:
    00029         Add any additional defines you need
    00030 */
    00031
    00032 #define     DIR_ENCRYPT     0       /* Are we encrpyting? */
    00033 #define     DIR_DECRYPT     1       /* Are we decrpyting? */
    00034 #define     MODE_ECB        1       /* Are we ciphering in ECB mode? */
    00035 #define     MODE_CBC        2       /* Are we ciphering in CBC mode? */
    00036 #define     MODE_CFB1       3       /* Are we ciphering in 1-bit CFB mode? */
    00037
    00038 #define     TRUE            1
    00039 #define     FALSE           0
    00040
    00041 #define     BAD_KEY_DIR         -1  /* Key direction is invalid (unknown value) */
    00042 #define     BAD_KEY_MAT         -2  /* Key material not of correct length */
    00043 #define     BAD_KEY_INSTANCE    -3  /* Key passed is not valid */
    00044 #define     BAD_CIPHER_MODE     -4  /* Params struct passed to cipherInit invalid */
    00045 #define     BAD_CIPHER_STATE    -5  /* Cipher in wrong state (e.g., not initialized) */
    00046
    00047 /* CHANGE POSSIBLE: inclusion of algorithm specific defines */
    00048 /* TWOFISH specific definitions */
    00049 #define     MAX_KEY_SIZE        64  /* # of ASCII chars needed to represent a key */
    00050 #define     MAX_IV_SIZE         16  /* # of bytes needed to represent an IV */
    00051 #define     BAD_INPUT_LEN       -6  /* inputLen not a multiple of block size */
    00052 #define     BAD_PARAMS          -7  /* invalid parameters */
    00053 #define     BAD_IV_MAT          -8  /* invalid IV text */
    00054 #define     BAD_ENDIAN          -9  /* incorrect endianness define */
    00055 #define     BAD_ALIGN32         -10 /* incorrect 32-bit alignment */
    00056
    00057 #define     BLOCK_SIZE          128 /* number of bits per block */
    00058 #define     MAX_ROUNDS           16 /* max # rounds (for allocating subkey array) */
    00059 #define     ROUNDS_128           16 /* default number of rounds for 128-bit keys*/
    00060 #define     ROUNDS_192           16 /* default number of rounds for 192-bit keys*/
    00061 #define     ROUNDS_256           16 /* default number of rounds for 256-bit keys*/
    00062 #define     MAX_KEY_BITS        256 /* max number of bits of key */
    00063 #define     MIN_KEY_BITS        128 /* min number of bits of key (zero pad) */
    00064 #define     VALID_SIG    0x48534946 /* initialization signature ('FISH') */
    00065 #define     MCT_OUTER           400 /* MCT outer loop */
    00066 #define     MCT_INNER         10000 /* MCT inner loop */
    00067 #define     REENTRANT             1 /* nonzero forces reentrant code (slightly slower) */
    00068
    00069 #define     INPUT_WHITEN        0   /* subkey array indices */
    00070 #define     OUTPUT_WHITEN       ( INPUT_WHITEN + BLOCK_SIZE/32)
    00071 #define     ROUND_SUBKEYS       (OUTPUT_WHITEN + BLOCK_SIZE/32) /* use 2 * (# rounds) */
    00072 #define     TOTAL_SUBKEYS       (ROUND_SUBKEYS + 2*MAX_ROUNDS)
    00073
    00074 /* Typedefs:
    00075     Typedef'ed data storage elements. Add any algorithm specific
    00076     parameters at the bottom of the structs as appropriate.
    00077 */
    00078
    00079 typedef unsigned char BYTE;
    00080 typedef unsigned long DWORD;        /* 32-bit unsigned quantity */
    00081 typedef DWORD fullSbox[4][256];
    00082
    00083 /* The structure for key information */
    00084 typedef struct
    00085     {
    00086     BYTE direction;                 /* Key used for encrypting or decrypting? */
    00087 #if ALIGN32
    00088     BYTE dummyAlign[3];             /* keep 32-bit alignment */
    00089 #endif
    00090     int  keyLen;                    /* Length of the key */
    00091     char keyMaterial[MAX_KEY_SIZE+4];/* Raw key data in ASCII */
    00092
    00093     /* Twofish-specific parameters: */
    00094     DWORD keySig;                   /* set to VALID_SIG by makeKey() */
    00095     int   numRounds;                /* number of rounds in cipher */
    00096     DWORD key32[MAX_KEY_BITS/32];   /* actual key bits, in dwords */
    00097     DWORD sboxKeys[MAX_KEY_BITS/64];/* key bits used for S-boxes */
    00098     DWORD subKeys[TOTAL_SUBKEYS];   /* round subkeys, input/output whitening bits */
    00099 #if REENTRANT
    00100     fullSbox sBox8x32;              /* fully expanded S-box */
    00101   #if defined(COMPILE_KEY) && defined(USE_ASM)
    00102 #undef  VALID_SIG
    00103 #define VALID_SIG    0x504D4F43     /* 'COMP':  C is compiled with -DCOMPILE_KEY */
    00104     DWORD cSig1;                    /* set after first "compile" (zero at "init") */
    00105     void *encryptFuncPtr;           /* ptr to asm encrypt function */
    00106     void *decryptFuncPtr;           /* ptr to asm decrypt function */
    00107     DWORD codeSize;                 /* size of compiledCode */
    00108     DWORD cSig2;                    /* set after first "compile" */
    00109     BYTE  compiledCode[5000];       /* make room for the code itself */
    00110   #endif
    00111 #endif
    00112     } keyInstance;
    00113
    00114 /* The structure for cipher information */
    00115 typedef struct
    00116     {
    00117     BYTE  mode;                     /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
    00118 #if ALIGN32
    00119     BYTE dummyAlign[3];             /* keep 32-bit alignment */
    00120 #endif
    00121     BYTE  IV[MAX_IV_SIZE];          /* CFB1 iv bytes  (CBC uses iv32) */
    00122
    00123     /* Twofish-specific parameters: */
    00124     DWORD cipherSig;                /* set to VALID_SIG by cipherInit() */
    00125     DWORD iv32[BLOCK_SIZE/32];      /* CBC IV bytes arranged as dwords */
    00126     } cipherInstance;
    00127
    00128 /* Function protoypes */
    00129 int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial);
    00130
    00131 int cipherInit(cipherInstance *cipher, BYTE mode, char *IV);
    00132
    00133 int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
    00134                 int inputLen, BYTE *outBuffer);
    00135
    00136 int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
    00137                 int inputLen, BYTE *outBuffer);
    00138
    00139 int reKey(keyInstance *key);    /* do key schedule using modified key.keyDwords */
    00140
    00141 /* API to check table usage, for use in ECB_TBL KAT */
    00142 #define     TAB_DISABLE         0
    00143 #define     TAB_ENABLE          1
    00144 #define     TAB_RESET           2
    00145 #define     TAB_QUERY           3
    00146 #define     TAB_MIN_QUERY       50
    00147 int TableOp(int op);
    00148
    00149
    00150 //#define       CONST               /* helpful C++ syntax sugar, NOP for ANSI C */
    00151
    00152 #if BLOCK_SIZE == 128           /* optimize block copies */
    00153 #define     Copy1(d,s,N)    ((DWORD *)(d))[N] = ((DWORD *)(s))[N]
    00154 #define     BlockCopy(d,s)  { Copy1(d,s,0);Copy1(d,s,1);Copy1(d,s,2);Copy1(d,s,3); }
    00155 #else
    00156 #define     BlockCopy(d,s)  { memcpy(d,s,BLOCK_SIZE/8); }
    00157 #endif
    00158
    00159
    00160 #ifdef TEST_2FISH
    00161 /*                      ----- EXAMPLES -----
    00162
    00163 Unfortunately, the AES API is somewhat clumsy, and it is not entirely
    00164 obvious how to use the above functions.  In particular, note that
    00165 makeKey() takes an ASCII hex nibble key string (e.g., 32 characters
    00166 for a 128-bit key), which is rarely the way that keys are internally
    00167 represented.  The reKey() function uses instead the keyInstance.key32
    00168 array of key bits and is the preferred method.  In fact, makeKey()
    00169 initializes some internal keyInstance state, then parse the ASCII
    00170 string into the binary key32, and calls reKey().  To initialize the
    00171 keyInstance state, use a 'dummy' call to makeKey(); i.e., set the
    00172 keyMaterial parameter to NULL.  Then use reKey() for all key changes.
    00173 Similarly, cipherInit takes an IV string in ASCII hex, so a dummy setup
    00174 call with a null IV string will skip the ASCII parse.
    00175
    00176 Note that CFB mode is not well tested nor defined by AES, so using the
    00177 Twofish MODE_CFB it not recommended.  If you wish to implement a CFB mode,
    00178 build it external to the Twofish code, using the Twofish functions only
    00179 in ECB mode.
    00180
    00181 Below is a sample piece of code showing how the code is typically used
    00182 to set up a key, encrypt, and decrypt.  Error checking is somewhat limited
    00183 in this example.  Pseudorandom bytes are used for all key and text.
    00184
    00185 If you compile TWOFISH2.C or TWOFISH.C as a DOS (or Windows Console) app
    00186 with this code enabled, the test will be run.  For example, using
    00187 Borland C, you would compile using:
    00188   BCC32 -DTEST_2FISH twofish2.c
    00189 to run the test on the optimized code, or
    00190   BCC32 -DTEST_2FISH twofish.c
    00191 to run the test on the pedagogical code.
    00192
    00193 */
    00194
    00195 #include <stdio.h>
    00196 #include <stdlib.h>
    00197 #include <time.h>
    00198 #include <string.h>
    00199
    00200 #define MAX_BLK_CNT     4       /* max # blocks per call in TestTwofish */
    00201 int TestTwofish(int mode,int keySize) /* keySize must be 128, 192, or 256 */
    00202     {                           /* return 0 iff test passes */
    00203     keyInstance    ki;          /* key information, including tables */
    00204     cipherInstance ci;          /* keeps mode (ECB, CBC) and IV */
    00205     BYTE  plainText[MAX_BLK_CNT*(BLOCK_SIZE/8)];
    00206     BYTE cipherText[MAX_BLK_CNT*(BLOCK_SIZE/8)];
    00207     BYTE decryptOut[MAX_BLK_CNT*(BLOCK_SIZE/8)];
    00208     BYTE iv[BLOCK_SIZE/8];
    00209     int  i,byteCnt;
    00210
    00211     if (makeKey(&ki,DIR_ENCRYPT,keySize,NULL) != TRUE)
    00212         return 1;               /* 'dummy' setup for a 128-bit key */
    00213     if (cipherInit(&ci,mode,NULL) != TRUE)
    00214         return 1;               /* 'dummy' setup for cipher */
    00215
    00216     for (i=0;i<keySize/32;i++)  /* select key bits */
    00217         ki.key32[i]=0x10003 * rand();
    00218     reKey(&ki);                 /* run the key schedule */
    00219
    00220     if (mode != MODE_ECB)       /* set up random iv (if needed)*/
    00221         {
    00222         for (i=0;i<sizeof(iv);i++)
    00223             iv[i]=(BYTE) rand();
    00224         memcpy(ci.iv32,iv,sizeof(ci.iv32)); /* copy the IV to ci */
    00225         }
    00226
    00227     /* select number of bytes to encrypt (multiple of block) */
    00228     /* e.g., byteCnt = 16, 32, 48, 64 */
    00229     byteCnt = (BLOCK_SIZE/8) * (1 + (rand() % MAX_BLK_CNT));
    00230
    00231     for (i=0;i<byteCnt;i++)     /* generate test data */
    00232         plainText[i]=(BYTE) rand();
    00233
    00234     /* encrypt the bytes */
    00235     if (blockEncrypt(&ci,&ki, plainText,byteCnt*8,cipherText) != byteCnt*8)
    00236         return 1;
    00237
    00238     /* decrypt the bytes */
    00239     if (mode != MODE_ECB)       /* first re-init the IV (if needed) */
    00240         memcpy(ci.iv32,iv,sizeof(ci.iv32));
    00241
    00242     if (blockDecrypt(&ci,&ki,cipherText,byteCnt*8,decryptOut) != byteCnt*8)
    00243         return 1;
    00244
    00245     /* make sure the decrypt output matches original plaintext */
    00246     if (memcmp(plainText,decryptOut,byteCnt))
    00247         return 1;
    00248
    00249     return 0;                   /* tests passed! */
    00250     }
    00251
    00252 void main(void)
    00253     {
    00254     int testCnt,keySize;
    00255
    00256     srand((unsigned) time(NULL));   /* randomize */
    00257
    00258     for (keySize=128;keySize<=256;keySize+=64)
    00259         for (testCnt=0;testCnt<10;testCnt++)
    00260             {
    00261             if (TestTwofish(MODE_ECB,keySize))
    00262                 { printf("ECB Failure at keySize=%d",keySize); return; }
    00263             if (TestTwofish(MODE_CBC,keySize))
    00264                 { printf("CBC Failure at keySize=%d",keySize); return; }
    00265             }
    00266     printf("Tests passed");
    00267     }
    00268 #endif /* TEST_2FISH */