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