1 /*
2 ---------------------------------------------------------------------------
3 Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
4
5 The redistribution and use of this software (with or without changes)
6 is allowed without the payment of fees or royalties provided that:
7
8 source code distributions include the above copyright notice, this
9 list of conditions and the following disclaimer;
10
11 binary distributions include the above copyright notice, this list
12 of conditions and the following disclaimer in their documentation.
13
14 This software is provided 'as is' with no explicit or implied warranties
15 in respect of its operation, including, but not limited to, correctness
16 and fitness for purpose.
17 ---------------------------------------------------------------------------
18 Issue Date: 20/12/2007
19 */
20
21 // An example of the use of AES (Rijndael) for file encryption. This code
22 // implements AES in CBC mode with ciphertext stealing when the file length
23 // is greater than one block (16 bytes). This code is an example of how to
24 // use AES and is not intended for real use since it does not provide any
25 // file integrity checking.
26 //
27 // The Command line is:
28 //
29 // aesxam input_file_name output_file_name [D|E] hexadecimalkey
30 //
31 // where E gives encryption and D decryption of the input file into the
32 // output file using the given hexadecimal key string. The later is a
33 // hexadecimal sequence of 32, 48 or 64 digits. Examples to encrypt or
34 // decrypt aes.c into aes.enc are:
35 //
36 // aesxam file.c file.enc E 0123456789abcdeffedcba9876543210
37 //
38 // aesxam file.enc file2.c D 0123456789abcdeffedcba9876543210
39 //
40 // which should return a file 'file2.c' identical to 'file.c'
41 //
42 // CIPHERTEXT STEALING
43 //
44 // Ciphertext stealing modifies the encryption of the last two CBC
45 // blocks. It can be applied invariably to the last two plaintext
46 // blocks or only applied when the last block is a partial one. In
47 // this code it is only applied if there is a partial block. For
48 // a plaintext consisting of N blocks, with the last block possibly
49 // a partial one, ciphertext stealing works as shown below (note the
50 // reversal of the last two ciphertext blocks). During decryption
51 // the part of the C:N-1 block that is not transmitted (X) can be
52 // obtained from the decryption of the penultimate ciphertext block
53 // since the bytes in X are xored with the zero padding appended to
54 // the last plaintext block.
55 //
56 // This is a picture of the processing of the last
57 // plaintext blocks during encryption:
58 //
59 // +---------+ +---------+ +---------+ +-------+-+
60 // | P:N-4 | | P:N-3 | | P:N-2 | | P:N-1 |0|
61 // +---------+ +---------+ +---------+ +-------+-+
62 // | | | |
63 // v v v v
64 // +----->x +----->x +----->x +----->x x = xor
65 // | | | | | | | |
66 // | v | v | v | v
67 // | +---+ | +---+ | +---+ | +---+
68 // | | E | | | E | | | E | | | E |
69 // | +---+ | +---+ | +---+ | +---+
70 // | | | | | | | |
71 // | | | | | v | +---+
72 // | | | | | +-------+-+ | |
73 // | | | | | | C:N-1 |X| | |
74 // | | | | | +-------+-+ ^ |
75 // | | | | | || | |
76 // | | | | | |+------+ |
77 // | | | | | +----------|--+
78 // | | | | | | |
79 // | | | | | +---------+ |
80 // | | | | | | |
81 // | v | v | v v
82 // | +---------+ | +---------+ | +---------+ +-------+
83 // -+ | C:N-4 |-+ | C:N-3 |-+ | C:N-2 | | C:N-1 |
84 // +---------+ +---------+ +---------+ +-------+
85 //
86 // And this is a picture of the processing of the last
87 // ciphertext blocks during decryption:
88 //
89 // +---------+ +---------+ +---------+ +-------+
90 // -+ | C:N-4 |-+ | C:N-3 |-+ | C:N-2 | | C:N-1 |
91 // | +---------+ | +---------+ | +---------+ +-------+
92 // | | | | | | |
93 // | v | v | v +--------|----+
94 // | +---+ | +---+ | +---+ | +--<--+ |
95 // | | D | | | D | | | D | | | | |
96 // | +---+ | +---+ | +---+ | | v v
97 // | | | | | | ^ | +-------+-+
98 // | v | v | v | | | C:N-1 |X|
99 // +----->x +----->x | +-------+-+ | +-------+-+
100 // | | | | |X| | |
101 // | | | +-------+-+ | v
102 // | | | | | +---+
103 // | | | | v | D |
104 // | | | +------>x +---+
105 // | | | | |
106 // | | +----->x<-----|------+ x = xor
107 // | | | +-----+
108 // | | | |
109 // v v v v
110 // +---------+ +---------+ +---------+ +-------+
111 // | P:N-4 | | P:N-3 | | P:N-2 | | P:N-1 |
112 // +---------+ +---------+ +---------+ +-------+
113
114 #include <stdio.h>
115 #include <ctype.h>
116
117 #include "aes.h"
118 #include "rdtsc.h"
119
120 #define BLOCK_LEN 16
121
122 #define OK 0
123 #define READ_ERROR -7
124 #define WRITE_ERROR -8
125
126 // A Pseudo Random Number Generator (PRNG) used for the
127 // Initialisation Vector. The PRNG is George Marsaglia's
128 // Multiply-With-Carry (MWC) PRNG that concatenates two
129 // 16-bit MWC generators:
130 // x(n)=36969 * x(n-1) + carry mod 2^16
131 // y(n)=18000 * y(n-1) + carry mod 2^16
132 // to produce a combined PRNG with a period of about 2^60.
133 // The Pentium cycle counter is used to initialise it. This
134 // is crude but the IV does not really need to be secret.
135
136 #define RAND(a,b) (((a = 36969 * (a & 65535) + (a >> 16)) << 16) + \
137 (b = 18000 * (b & 65535) + (b >> 16)) )
138
fillrand(unsigned char * buf,const int len)139 void fillrand(unsigned char *buf, const int len)
140 { static unsigned long a[2], mt = 1, count = 4;
141 static unsigned char r[4];
142 int i;
143
144 if(mt) { mt = 0; *(unsigned long long*)a = read_tsc(); }
145
146 for(i = 0; i < len; ++i)
147 {
148 if(count == 4)
149 {
150 *(unsigned long*)r = RAND(a[0], a[1]);
151 count = 0;
152 }
153
154 buf[i] = r[count++];
155 }
156 }
157
encfile(FILE * fin,FILE * fout,aes_encrypt_ctx ctx[1])158 int encfile(FILE *fin, FILE *fout, aes_encrypt_ctx ctx[1])
159 { unsigned char dbuf[3 * BLOCK_LEN];
160 unsigned long i, len, wlen = BLOCK_LEN;
161
162 // When ciphertext stealing is used, we three ciphertext blocks so
163 // we use a buffer that is three times the block length. The buffer
164 // pointers b1, b2 and b3 point to the buffer positions of three
165 // ciphertext blocks, b3 being the most recent and b1 being the
166 // oldest. We start with the IV in b1 and the block to be decrypted
167 // in b2.
168
169 // set a random IV
170
171 fillrand(dbuf, BLOCK_LEN);
172
173 // read the first file block
174 len = (unsigned long) fread((char*)dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin);
175
176 if(len < BLOCK_LEN)
177 { // if the file length is less than one block
178
179 // xor the file bytes with the IV bytes
180 for(i = 0; i < len; ++i)
181 dbuf[i + BLOCK_LEN] ^= dbuf[i];
182
183 // encrypt the top 16 bytes of the buffer
184 aes_encrypt(dbuf + len, dbuf + len, ctx);
185
186 len += BLOCK_LEN;
187 // write the IV and the encrypted file bytes
188 if(fwrite((char*)dbuf, 1, len, fout) != len)
189 return WRITE_ERROR;
190
191 return OK;
192 }
193 else // if the file length is more 16 bytes
194 { unsigned char *b1 = dbuf, *b2 = b1 + BLOCK_LEN, *b3 = b2 + BLOCK_LEN, *bt;
195
196 // write the IV
197 if(fwrite((char*)dbuf, 1, BLOCK_LEN, fout) != BLOCK_LEN)
198 return WRITE_ERROR;
199
200 for( ; ; )
201 {
202 // read the next block to see if ciphertext stealing is needed
203 len = (unsigned long)fread((char*)b3, 1, BLOCK_LEN, fin);
204
205 // do CBC chaining prior to encryption for current block (in b2)
206 for(i = 0; i < BLOCK_LEN; ++i)
207 b1[i] ^= b2[i];
208
209 // encrypt the block (now in b1)
210 aes_encrypt(b1, b1, ctx);
211
212 if(len != 0 && len != BLOCK_LEN) // use ciphertext stealing
213 {
214 // set the length of the last block
215 wlen = len;
216
217 // xor ciphertext into last block
218 for(i = 0; i < len; ++i)
219 b3[i] ^= b1[i];
220
221 // move 'stolen' ciphertext into last block
222 for(i = len; i < BLOCK_LEN; ++i)
223 b3[i] = b1[i];
224
225 // encrypt this block
226 aes_encrypt(b3, b3, ctx);
227
228 // and write it as the second to last encrypted block
229 if(fwrite((char*)b3, 1, BLOCK_LEN, fout) != BLOCK_LEN)
230 return WRITE_ERROR;
231 }
232
233 // write the encrypted block
234 if(fwrite((char*)b1, 1, wlen, fout) != wlen)
235 return WRITE_ERROR;
236
237 if(len != BLOCK_LEN)
238 return OK;
239
240 // advance the buffer pointers
241 bt = b3, b3 = b2, b2 = b1, b1 = bt;
242 }
243 }
244 }
245
decfile(FILE * fin,FILE * fout,aes_decrypt_ctx ctx[1])246 int decfile(FILE *fin, FILE *fout, aes_decrypt_ctx ctx[1])
247 { unsigned char dbuf[3 * BLOCK_LEN], buf[BLOCK_LEN];
248 unsigned long i, len, wlen = BLOCK_LEN;
249
250 // When ciphertext stealing is used, we three ciphertext blocks so
251 // we use a buffer that is three times the block length. The buffer
252 // pointers b1, b2 and b3 point to the buffer positions of three
253 // ciphertext blocks, b3 being the most recent and b1 being the
254 // oldest. We start with the IV in b1 and the block to be decrypted
255 // in b2.
256
257 len = (unsigned long)fread((char*)dbuf, 1, 2 * BLOCK_LEN, fin);
258
259 if(len < 2 * BLOCK_LEN) // the original file is less than one block in length
260 {
261 len -= BLOCK_LEN;
262 // decrypt from position len to position len + BLOCK_LEN
263 aes_decrypt(dbuf + len, dbuf + len, ctx);
264
265 // undo the CBC chaining
266 for(i = 0; i < len; ++i)
267 dbuf[i] ^= dbuf[i + BLOCK_LEN];
268
269 // output the decrypted bytes
270 if(fwrite((char*)dbuf, 1, len, fout) != len)
271 return WRITE_ERROR;
272
273 return OK;
274 }
275 else
276 { unsigned char *b1 = dbuf, *b2 = b1 + BLOCK_LEN, *b3 = b2 + BLOCK_LEN, *bt;
277
278 for( ; ; ) // while some ciphertext remains, prepare to decrypt block b2
279 {
280 // read in the next block to see if ciphertext stealing is needed
281 len = fread((char*)b3, 1, BLOCK_LEN, fin);
282
283 // decrypt the b2 block
284 aes_decrypt(b2, buf, ctx);
285
286 if(len == 0 || len == BLOCK_LEN) // no ciphertext stealing
287 {
288 // unchain CBC using the previous ciphertext block in b1
289 for(i = 0; i < BLOCK_LEN; ++i)
290 buf[i] ^= b1[i];
291 }
292 else // partial last block - use ciphertext stealing
293 {
294 wlen = len;
295
296 // produce last 'len' bytes of plaintext by xoring with
297 // the lowest 'len' bytes of next block b3 - C[N-1]
298 for(i = 0; i < len; ++i)
299 buf[i] ^= b3[i];
300
301 // reconstruct the C[N-1] block in b3 by adding in the
302 // last (BLOCK_LEN - len) bytes of C[N-2] in b2
303 for(i = len; i < BLOCK_LEN; ++i)
304 b3[i] = buf[i];
305
306 // decrypt the C[N-1] block in b3
307 aes_decrypt(b3, b3, ctx);
308
309 // produce the last but one plaintext block by xoring with
310 // the last but two ciphertext block
311 for(i = 0; i < BLOCK_LEN; ++i)
312 b3[i] ^= b1[i];
313
314 // write decrypted plaintext blocks
315 if(fwrite((char*)b3, 1, BLOCK_LEN, fout) != BLOCK_LEN)
316 return WRITE_ERROR;
317 }
318
319 // write the decrypted plaintext block
320 if(fwrite((char*)buf, 1, wlen, fout) != wlen)
321 return WRITE_ERROR;
322
323 if(len != BLOCK_LEN)
324 return OK;
325
326 // advance the buffer pointers
327 bt = b1, b1 = b2, b2 = b3, b3 = bt;
328 }
329 }
330 }
331
main(int argc,char * argv[])332 int main(int argc, char *argv[])
333 { FILE *fin = 0, *fout = 0;
334 char *cp, ch, key[32];
335 int i, by = 0, key_len, err = 0;
336
337 if(argc != 5 || toupper(*argv[3]) != 'D' && toupper(*argv[3]) != 'E')
338 {
339 printf("usage: aesxam in_filename out_filename [d/e] key_in_hex\n");
340 err = -1; goto exit;
341 }
342
343 aes_init(); // in case dynamic AES tables are being used
344
345 cp = argv[4]; // this is a pointer to the hexadecimal key digits
346 i = 0; // this is a count for the input digits processed
347
348 while(i < 64 && *cp) // the maximum key length is 32 bytes and
349 { // hence at most 64 hexadecimal digits
350 ch = toupper(*cp++); // process a hexadecimal digit
351 if(ch >= '0' && ch <= '9')
352 by = (by << 4) + ch - '0';
353 else if(ch >= 'A' && ch <= 'F')
354 by = (by << 4) + ch - 'A' + 10;
355 else // error if not hexadecimal
356 {
357 printf("key must be in hexadecimal notation\n");
358 err = -2; goto exit;
359 }
360
361 // store a key byte for each pair of hexadecimal digits
362 if(i++ & 1)
363 key[i / 2 - 1] = by & 0xff;
364 }
365
366 if(*cp)
367 {
368 printf("The key value is too long\n");
369 err = -3; goto exit;
370 }
371 else if(i < 32 || (i & 15))
372 {
373 printf("The key length must be 32, 48 or 64 hexadecimal digits\n");
374 err = -4; goto exit;
375 }
376
377 key_len = i / 2;
378
379 if(!(fin = fopen(argv[1], "rb"))) // try to open the input file
380 {
381 printf("The input file: %s could not be opened\n", argv[1]);
382 err = -5; goto exit;
383 }
384
385 if(!(fout = fopen(argv[2], "wb"))) // try to open the output file
386 {
387 printf("The output file: %s could not be opened\n", argv[2]);
388 err = -6; goto exit;
389 }
390
391 if(toupper(*argv[3]) == 'E') // encryption in Cipher Block Chaining mode
392 { aes_encrypt_ctx ctx[1];
393
394 aes_encrypt_key((unsigned char*)key, key_len, ctx);
395
396 err = encfile(fin, fout, ctx);
397 }
398 else // decryption in Cipher Block Chaining mode
399 { aes_decrypt_ctx ctx[1];
400
401 aes_decrypt_key((unsigned char*)key, key_len, ctx);
402
403 err = decfile(fin, fout, ctx);
404 }
405 exit:
406 if(err == READ_ERROR)
407 printf("Error reading from input file: %s\n", argv[1]);
408
409 if(err == WRITE_ERROR)
410 printf("Error writing to output file: %s\n", argv[2]);
411
412 if(fout)
413 fclose(fout);
414
415 if(fin)
416 fclose(fin);
417
418 return err;
419 }
420