1 |
root |
1.1 |
#ifndef AES_H |
2 |
|
|
#define AES_H |
3 |
|
|
/* aes.h */ |
4 |
|
|
|
5 |
|
|
/* ---------- See examples at end of this file for typical usage -------- */ |
6 |
|
|
|
7 |
|
|
/* AES Cipher header file for ANSI C Submissions |
8 |
|
|
Lawrence E. Bassham III |
9 |
|
|
Computer Security Division |
10 |
|
|
National Institute of Standards and Technology |
11 |
|
|
|
12 |
|
|
This sample is to assist implementers developing to the |
13 |
|
|
Cryptographic API Profile for AES Candidate Algorithm Submissions. |
14 |
|
|
Please consult this document as a cross-reference. |
15 |
|
|
|
16 |
|
|
ANY CHANGES, WHERE APPROPRIATE, TO INFORMATION PROVIDED IN THIS FILE |
17 |
|
|
MUST BE DOCUMENTED. CHANGES ARE ONLY APPROPRIATE WHERE SPECIFIED WITH |
18 |
|
|
THE STRING "CHANGE POSSIBLE". FUNCTION CALLS AND THEIR PARAMETERS |
19 |
|
|
CANNOT BE CHANGED. STRUCTURES CAN BE ALTERED TO ALLOW IMPLEMENTERS TO |
20 |
|
|
INCLUDE IMPLEMENTATION SPECIFIC INFORMATION. |
21 |
|
|
*/ |
22 |
|
|
|
23 |
|
|
/* Includes: |
24 |
|
|
Standard include files |
25 |
|
|
*/ |
26 |
|
|
|
27 |
|
|
#include <stdio.h> |
28 |
|
|
#include "platform.h" /* platform-specific defines */ |
29 |
|
|
|
30 |
|
|
/* Defines: |
31 |
|
|
Add any additional defines you need |
32 |
|
|
*/ |
33 |
|
|
|
34 |
|
|
#define DIR_ENCRYPT 0 /* Are we encrpyting? */ |
35 |
|
|
#define DIR_DECRYPT 1 /* Are we decrpyting? */ |
36 |
|
|
#define MODE_ECB 1 /* Are we ciphering in ECB mode? */ |
37 |
|
|
#define MODE_CBC 2 /* Are we ciphering in CBC mode? */ |
38 |
|
|
#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */ |
39 |
|
|
|
40 |
|
|
#define BAD_KEY_DIR -5 /* Key direction is invalid (unknown value) */ |
41 |
|
|
#define BAD_KEY_MAT -6 /* Key material not of correct length */ |
42 |
|
|
#define BAD_KEY_INSTANCE -7 /* Key passed is not valid */ |
43 |
|
|
#define BAD_CIPHER_MODE -8 /* Params struct passed to cipherInit invalid */ |
44 |
|
|
#define BAD_CIPHER_STATE -9 /* Cipher in wrong state (e.g., not initialized) */ |
45 |
|
|
|
46 |
|
|
/* CHANGE POSSIBLE: inclusion of algorithm specific defines */ |
47 |
|
|
/* TWOFISH specific definitions */ |
48 |
|
|
#define MAX_KEY_SIZE 64 /* # of ASCII chars needed to represent a key */ |
49 |
|
|
#define MAX_IV_SIZE 16 /* # of bytes needed to represent an IV */ |
50 |
|
|
#define BAD_INPUT_LEN -6 /* inputLen not a multiple of block size */ |
51 |
|
|
#define BAD_PARAMS -7 /* invalid parameters */ |
52 |
|
|
#define BAD_IV_MAT -8 /* invalid IV text */ |
53 |
|
|
#define BAD_ENDIAN -9 /* incorrect endianness define */ |
54 |
|
|
#define BAD_ALIGN32 -10 /* incorrect 32-bit alignment */ |
55 |
|
|
|
56 |
|
|
#define BLOCK_SIZE 128 /* number of bits per block */ |
57 |
|
|
#define MAX_ROUNDS 16 /* max # rounds (for allocating subkey array) */ |
58 |
|
|
#define ROUNDS_128 16 /* default number of rounds for 128-bit keys*/ |
59 |
|
|
#define ROUNDS_192 16 /* default number of rounds for 192-bit keys*/ |
60 |
|
|
#define ROUNDS_256 16 /* default number of rounds for 256-bit keys*/ |
61 |
|
|
#define MAX_KEY_BITS 256 /* max number of bits of key */ |
62 |
|
|
#define MIN_KEY_BITS 128 /* min number of bits of key (zero pad) */ |
63 |
|
|
#define VALID_SIG 0x48534946 /* initialization signature ('FISH') */ |
64 |
|
|
#define MCT_OUTER 400 /* MCT outer loop */ |
65 |
|
|
#define MCT_INNER 10000 /* MCT inner loop */ |
66 |
|
|
#define REENTRANT 1 /* nonzero forces reentrant code (slightly slower) */ |
67 |
|
|
|
68 |
|
|
#define INPUT_WHITEN 0 /* subkey array indices */ |
69 |
|
|
#define OUTPUT_WHITEN ( INPUT_WHITEN + BLOCK_SIZE/32) |
70 |
|
|
#define ROUND_SUBKEYS (OUTPUT_WHITEN + BLOCK_SIZE/32) /* use 2 * (# rounds) */ |
71 |
|
|
#define TOTAL_SUBKEYS (ROUND_SUBKEYS + 2*MAX_ROUNDS) |
72 |
|
|
|
73 |
|
|
/* Typedefs: |
74 |
|
|
Typedef'ed data storage elements. Add any algorithm specific |
75 |
|
|
parameters at the bottom of the structs as appropriate. |
76 |
|
|
*/ |
77 |
|
|
|
78 |
|
|
typedef DWORD fullSbox[4][256]; |
79 |
|
|
|
80 |
|
|
/* The structure for key information */ |
81 |
|
|
typedef struct |
82 |
|
|
{ |
83 |
|
|
BYTE direction; /* Key used for encrypting or decrypting? */ |
84 |
|
|
#if ALIGN32 |
85 |
|
|
BYTE dummyAlign[3]; /* keep 32-bit alignment */ |
86 |
|
|
#endif |
87 |
|
|
int keyLen; /* Length of the key */ |
88 |
|
|
|
89 |
|
|
/* Twofish-specific parameters: */ |
90 |
|
|
DWORD keySig; /* set to VALID_SIG by makeKey() */ |
91 |
|
|
int numRounds; /* number of rounds in cipher */ |
92 |
|
|
DWORD key32[MAX_KEY_BITS/32]; /* actual key bits, in dwords */ |
93 |
|
|
DWORD sboxKeys[MAX_KEY_BITS/64];/* key bits used for S-boxes */ |
94 |
|
|
DWORD subKeys[TOTAL_SUBKEYS]; /* round subkeys, input/output whitening bits */ |
95 |
|
|
#if REENTRANT |
96 |
|
|
fullSbox sBox8x32; /* fully expanded S-box */ |
97 |
|
|
#if defined(COMPILE_KEY) && defined(USE_ASM) |
98 |
|
|
#undef VALID_SIG |
99 |
|
|
#define VALID_SIG 0x504D4F43 /* 'COMP': C is compiled with -DCOMPILE_KEY */ |
100 |
|
|
DWORD cSig1; /* set after first "compile" (zero at "init") */ |
101 |
|
|
void *encryptFuncPtr; /* ptr to asm encrypt function */ |
102 |
|
|
void *decryptFuncPtr; /* ptr to asm decrypt function */ |
103 |
|
|
DWORD codeSize; /* size of compiledCode */ |
104 |
|
|
DWORD cSig2; /* set after first "compile" */ |
105 |
|
|
BYTE compiledCode[5000]; /* make room for the code itself */ |
106 |
|
|
#endif |
107 |
|
|
#endif |
108 |
|
|
} keyInstance; |
109 |
|
|
|
110 |
|
|
/* The structure for cipher information */ |
111 |
|
|
typedef struct |
112 |
|
|
{ |
113 |
|
|
BYTE mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */ |
114 |
|
|
#if ALIGN32 |
115 |
|
|
BYTE dummyAlign[3]; /* keep 32-bit alignment */ |
116 |
|
|
#endif |
117 |
|
|
BYTE IV[MAX_IV_SIZE]; /* CFB1 iv bytes (CBC uses iv32) */ |
118 |
|
|
|
119 |
|
|
/* Twofish-specific parameters: */ |
120 |
|
|
DWORD cipherSig; /* set to VALID_SIG by cipherInit() */ |
121 |
|
|
DWORD iv32[BLOCK_SIZE/32]; /* CBC IV bytes arranged as dwords */ |
122 |
|
|
} cipherInstance; |
123 |
|
|
|
124 |
|
|
/* Function protoypes */ |
125 |
root |
1.2 |
static int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial); |
126 |
root |
1.1 |
|
127 |
root |
1.2 |
static int cipherInit(cipherInstance *cipher, BYTE mode, char *IV); |
128 |
root |
1.1 |
|
129 |
root |
1.2 |
static int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, |
130 |
root |
1.1 |
int inputLen, BYTE *outBuffer); |
131 |
|
|
|
132 |
root |
1.2 |
static int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, |
133 |
root |
1.1 |
int inputLen, BYTE *outBuffer); |
134 |
|
|
|
135 |
root |
1.2 |
static int reKey(keyInstance *key); /* do key schedule using modified key.keyDwords */ |
136 |
root |
1.1 |
|
137 |
|
|
/* API to check table usage, for use in ECB_TBL KAT */ |
138 |
|
|
#define TAB_DISABLE 0 |
139 |
|
|
#define TAB_ENABLE 1 |
140 |
|
|
#define TAB_RESET 2 |
141 |
|
|
#define TAB_QUERY 3 |
142 |
|
|
#define TAB_MIN_QUERY 50 |
143 |
root |
1.2 |
static int TableOp(int op); |
144 |
root |
1.1 |
|
145 |
|
|
|
146 |
|
|
#define CONST /* helpful C++ syntax sugar, NOP for ANSI C */ |
147 |
|
|
|
148 |
|
|
#if BLOCK_SIZE == 128 /* optimize block copies */ |
149 |
|
|
#define Copy1(d,s,N) ((DWORD *)(d))[N] = ((DWORD *)(s))[N] |
150 |
|
|
#define BlockCopy(d,s) { Copy1(d,s,0);Copy1(d,s,1);Copy1(d,s,2);Copy1(d,s,3); } |
151 |
|
|
#else |
152 |
|
|
#define BlockCopy(d,s) { memcpy(d,s,BLOCK_SIZE/8); } |
153 |
|
|
#endif |
154 |
|
|
|
155 |
|
|
|
156 |
|
|
#ifdef TEST_2FISH |
157 |
|
|
/* ----- EXAMPLES ----- |
158 |
|
|
|
159 |
|
|
Unfortunately, the AES API is somewhat clumsy, and it is not entirely |
160 |
|
|
obvious how to use the above functions. In particular, note that |
161 |
|
|
makeKey() takes an ASCII hex nibble key string (e.g., 32 characters |
162 |
|
|
for a 128-bit key), which is rarely the way that keys are internally |
163 |
|
|
represented. The reKey() function uses instead the keyInstance.key32 |
164 |
|
|
array of key bits and is the preferred method. In fact, makeKey() |
165 |
|
|
initializes some internal keyInstance state, then parse the ASCII |
166 |
|
|
string into the binary key32, and calls reKey(). To initialize the |
167 |
|
|
keyInstance state, use a 'dummy' call to makeKey(); i.e., set the |
168 |
|
|
keyMaterial parameter to NULL. Then use reKey() for all key changes. |
169 |
|
|
Similarly, cipherInit takes an IV string in ASCII hex, so a dummy setup |
170 |
|
|
call with a null IV string will skip the ASCII parse. |
171 |
|
|
|
172 |
|
|
Note that CFB mode is not well tested nor defined by AES, so using the |
173 |
|
|
Twofish MODE_CFB it not recommended. If you wish to implement a CFB mode, |
174 |
|
|
build it external to the Twofish code, using the Twofish functions only |
175 |
|
|
in ECB mode. |
176 |
|
|
|
177 |
|
|
Below is a sample piece of code showing how the code is typically used |
178 |
|
|
to set up a key, encrypt, and decrypt. Error checking is somewhat limited |
179 |
|
|
in this example. Pseudorandom bytes are used for all key and text. |
180 |
|
|
|
181 |
|
|
If you compile TWOFISH2.C or TWOFISH.C as a DOS (or Windows Console) app |
182 |
|
|
with this code enabled, the test will be run. For example, using |
183 |
|
|
Borland C, you would compile using: |
184 |
|
|
BCC32 -DTEST_2FISH twofish2.c |
185 |
|
|
to run the test on the optimized code, or |
186 |
|
|
BCC32 -DTEST_2FISH twofish.c |
187 |
|
|
to run the test on the pedagogical code. |
188 |
|
|
|
189 |
|
|
*/ |
190 |
|
|
|
191 |
|
|
#include <stdio.h> |
192 |
|
|
#include <stdlib.h> |
193 |
|
|
#include <time.h> |
194 |
|
|
#include <string.h> |
195 |
|
|
|
196 |
|
|
#define MAX_BLK_CNT 4 /* max # blocks per call in TestTwofish */ |
197 |
root |
1.2 |
static int TestTwofish(int mode,int keySize) /* keySize must be 128, 192, or 256 */ |
198 |
root |
1.1 |
{ /* return 0 iff test passes */ |
199 |
|
|
keyInstance ki; /* key information, including tables */ |
200 |
|
|
cipherInstance ci; /* keeps mode (ECB, CBC) and IV */ |
201 |
|
|
BYTE plainText[MAX_BLK_CNT*(BLOCK_SIZE/8)]; |
202 |
|
|
BYTE cipherText[MAX_BLK_CNT*(BLOCK_SIZE/8)]; |
203 |
|
|
BYTE decryptOut[MAX_BLK_CNT*(BLOCK_SIZE/8)]; |
204 |
|
|
BYTE iv[BLOCK_SIZE/8]; |
205 |
|
|
int i,byteCnt; |
206 |
|
|
|
207 |
|
|
if (makeKey(&ki,DIR_ENCRYPT,keySize,NULL) != TRUE) |
208 |
|
|
return 1; /* 'dummy' setup for a 128-bit key */ |
209 |
|
|
if (cipherInit(&ci,mode,NULL) != TRUE) |
210 |
|
|
return 1; /* 'dummy' setup for cipher */ |
211 |
|
|
|
212 |
|
|
for (i=0;i<keySize/32;i++) /* select key bits */ |
213 |
|
|
ki.key32[i]=0x10003 * rand(); |
214 |
|
|
reKey(&ki); /* run the key schedule */ |
215 |
|
|
|
216 |
|
|
if (mode != MODE_ECB) /* set up random iv (if needed)*/ |
217 |
|
|
{ |
218 |
|
|
for (i=0;i<sizeof(iv);i++) |
219 |
|
|
iv[i]=(BYTE) rand(); |
220 |
|
|
memcpy(ci.iv32,iv,sizeof(ci.iv32)); /* copy the IV to ci */ |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
/* select number of bytes to encrypt (multiple of block) */ |
224 |
|
|
/* e.g., byteCnt = 16, 32, 48, 64 */ |
225 |
|
|
byteCnt = (BLOCK_SIZE/8) * (1 + (rand() % MAX_BLK_CNT)); |
226 |
|
|
|
227 |
|
|
for (i=0;i<byteCnt;i++) /* generate test data */ |
228 |
|
|
plainText[i]=(BYTE) rand(); |
229 |
|
|
|
230 |
|
|
/* encrypt the bytes */ |
231 |
|
|
if (blockEncrypt(&ci,&ki, plainText,byteCnt*8,cipherText) != byteCnt*8) |
232 |
|
|
return 1; |
233 |
|
|
|
234 |
|
|
/* decrypt the bytes */ |
235 |
|
|
if (mode != MODE_ECB) /* first re-init the IV (if needed) */ |
236 |
|
|
memcpy(ci.iv32,iv,sizeof(ci.iv32)); |
237 |
|
|
|
238 |
|
|
if (blockDecrypt(&ci,&ki,cipherText,byteCnt*8,decryptOut) != byteCnt*8) |
239 |
|
|
return 1; |
240 |
|
|
|
241 |
|
|
/* make sure the decrypt output matches original plaintext */ |
242 |
|
|
if (memcmp(plainText,decryptOut,byteCnt)) |
243 |
|
|
return 1; |
244 |
|
|
|
245 |
|
|
return 0; /* tests passed! */ |
246 |
|
|
} |
247 |
|
|
|
248 |
|
|
void main(void) |
249 |
|
|
{ |
250 |
|
|
int testCnt,keySize; |
251 |
|
|
|
252 |
|
|
srand((unsigned) time(NULL)); /* randomize */ |
253 |
|
|
|
254 |
|
|
for (keySize=128;keySize<=256;keySize+=64) |
255 |
|
|
for (testCnt=0;testCnt<10;testCnt++) |
256 |
|
|
{ |
257 |
|
|
if (TestTwofish(MODE_ECB,keySize)) |
258 |
|
|
{ printf("ECB Failure at keySize=%d",keySize); return; } |
259 |
|
|
if (TestTwofish(MODE_CBC,keySize)) |
260 |
|
|
{ printf("CBC Failure at keySize=%d",keySize); return; } |
261 |
|
|
} |
262 |
|
|
printf("Tests passed"); |
263 |
|
|
} |
264 |
|
|
#endif /* TEST_2FISH */ |
265 |
|
|
|
266 |
|
|
#endif |