root/WizardsToolkit/trunk/wizard/aes.c

Revision 1, 31.0 KB (checked in by cristy, 3 months ago)


Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                              AAA   EEEEE  SSSSS                             %
7%                             A   A  E      SS                                %
8%                             AAAAA  EEE     SSS                              %
9%                             A   A  E         SS                             %
10%                             A   A  EEEEE  SSSSS                             %
11%                                                                             %
12%                                                                             %
13%         Wizard's Toolkit Advanced Encryption Standard Cipher Methods        %
14%                                                                             %
15%                               Software Design                               %
16%                                 John Cristy                                 %
17%                                 March 2003                                  %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.wizards-toolkit.org/script/license.php                        %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include "wizard/studio.h"
43#include "wizard/aes.h"
44#include "wizard/exception.h"
45#include "wizard/exception-private.h"
46#include "wizard/memory_.h"
47
48/*
49  Typedef declarations.
50*/
51struct _AESInfo
52{
53  StringInfo
54    *key;
55
56  unsigned int
57    blocksize,
58    *encipher_key,
59    *decipher_key;
60
61  long
62    rounds;
63
64  time_t
65    timestamp;
66
67  unsigned long
68    signature;
69};
70
71/*
72  Define declarations.
73*/
74#define AESBlocksize 16
75
76/*
77  Global declarations.
78*/
79static unsigned char
80  InverseLog[256] =
81  {
82      1,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,
83     19,  53,  95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,
84     30,  34, 102, 170, 229,  52,  92, 228,  55,  89, 235,  38, 106, 190,
85    217, 112, 144, 171, 230,  49,  83, 245,   4,  12,  20,  60,  68, 204,
86     79, 209, 104, 184, 211, 110, 178, 205,  76, 212, 103, 169, 224,  59,
87     77, 215,  98, 166, 241,   8,  24,  40, 120, 136, 131, 158, 185, 208,
88    107, 189, 220, 127, 129, 152, 179, 206,  73, 219, 118, 154, 181, 196,
89     87, 249,  16,  48,  80, 240,  11,  29,  39, 105, 187, 214,  97, 163,
90    254,  25,  43, 125, 135, 146, 173, 236,  47, 113, 147, 174, 233,  32,
91     96, 160, 251,  22,  58,  78, 210, 109, 183, 194,  93, 231,  50,  86,
92    250,  21,  63,  65, 195,  94, 226,  61,  71, 201,  64, 192,  91, 237,
93     44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239,  42, 126,
94    130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193,  88, 232,  35,
95    101, 175, 234,  37, 111, 177, 200,  67, 197,  84, 252,  31,  33,  99,
96    165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,  69, 207,
97     74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,
98     18,  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,
99     13,  23,  57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180,
100    199,  82, 246,   1
101  },
102  Log[256] =
103  {
104      0,   0,  25,   1,  50,   2,  26, 198,  75, 199,  27, 104,  51, 238,
105    223,   3, 100,   4, 224,  14,  52, 141, 129, 239,  76, 113,   8, 200,
106    248, 105,  28, 193, 125, 194,  29, 181, 249, 185,  39, 106,  77, 228,
107    166, 114, 154, 201,   9, 120, 101,  47, 138,   5,  33,  15, 225,  36,
108     18, 240, 130,  69,  53, 147, 218, 142, 150, 143, 219, 189,  54, 208,
109    206, 148,  19,  92, 210, 241,  64,  70, 131,  56, 102, 221, 253,  48,
110    191,   6, 139,  98, 179,  37, 226, 152,  34, 136, 145,  16, 126, 110,
111     72, 195, 163, 182,  30,  66,  58, 107,  40,  84, 250, 133,  61, 186,
112     43, 121,  10,  21, 155, 159,  94, 202,  78, 212, 172, 229, 243, 115,
113    167,  87, 175,  88, 168,  80, 244, 234, 214, 116,  79, 174, 233, 213,
114    231, 230, 173, 232,  44, 215, 117, 122, 235,  22,  11, 245,  89, 203,
115     95, 176, 156, 169,  81, 160, 127,  12, 246, 111,  23, 196,  73, 236,
116    216,  67,  31,  45, 164, 118, 123, 183, 204, 187,  62,  90, 251,  96,
117    177, 134,  59,  82, 161, 108, 170,  85,  41, 157, 151, 178, 135, 144,
118     97, 190, 220, 252, 188, 149, 207, 205,  55,  63,  91, 209,  83,  57,
119    132, 60,   65, 162, 109,  71,  20,  42, 158,  93,  86, 242, 211, 171,
120     68,  17, 146, 217,  35,  32,  46, 137, 180, 124, 184,  38, 119, 153,
121    227, 165, 103,  74, 237, 222, 197,  49, 254,  24,  13,  99, 140, 128,
122    192, 247, 112,   7,
123  },
124  SBox[256] =
125  {
126     99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215,
127    171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175,
128    156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165,
129    229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,
130      7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110,
131     90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237,
132     32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239,
133    170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
134     81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255,
135    243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61,
136    100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238,
137    184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92,
138    194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
139     78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46,
140     28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62,
141    181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
142    225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,
143     40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15,
144    176,  84, 187, 22
145  };
146
147/*
148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149%                                                                             %
150%                                                                             %
151%                                                                             %
152%   A c q u i r e A E S I n f o                                               %
153%                                                                             %
154%                                                                             %
155%                                                                             %
156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157%
158%  AcquireAESInfo() allocate the AESInfo structure.
159%
160%  The format of the AcquireAESInfo method is:
161%
162%      AESInfo *AcquireAESInfo(void)
163%
164*/
165WizardExport AESInfo *AcquireAESInfo(void)
166{
167  AESInfo
168    *aes_info;
169
170  aes_info=(AESInfo *) AcquireWizardMemory(sizeof(*aes_info));
171  if (aes_info == (AESInfo *) NULL)
172    ThrowWizardFatalError(CipherDomain,MemoryError);
173  (void) ResetWizardMemory(aes_info,0,sizeof(*aes_info));
174  aes_info->blocksize=AESBlocksize;
175  aes_info->key=AcquireStringInfo(32);
176  aes_info->encipher_key=(unsigned int *) AcquireQuantumMemory(60UL,
177    sizeof(*aes_info->encipher_key));
178  aes_info->decipher_key=(unsigned int *) AcquireQuantumMemory(60UL,
179    sizeof(*aes_info->decipher_key));
180  if ((aes_info->key == (StringInfo *) NULL) ||
181      (aes_info->encipher_key == (unsigned int *) NULL) ||
182      (aes_info->decipher_key == (unsigned int *) NULL))
183    ThrowWizardFatalError(CipherDomain,MemoryError);
184  aes_info->timestamp=time((time_t *) NULL);
185  aes_info->signature=WizardSignature;
186  return(aes_info);
187}
188
189/*
190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191%                                                                             %
192%                                                                             %
193%                                                                             %
194%   D e c i p h e r A E S B l o c k                                           %
195%                                                                             %
196%                                                                             %
197%                                                                             %
198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199%
200%  DecipherAESBlock() deciphers a single block of ciphertext to produce a block
201%  of plaintext.
202%
203%  The format of the DecipherAESBlock method is:
204%
205%     void DecipherAES(AESInfo *aes_info,const unsigned char *ciphertext,
206%       unsigned char *plaintext)
207%
208%  A description of each parameter follows:
209%
210%    o aes_info: The cipher context.
211%
212%    o ciphertext: The cipher text.
213%
214%    o plainttext: The plaint text.
215%
216*/
217
218static inline void AddRoundKey(const unsigned int *ciphertext,
219  const unsigned int *key,unsigned int *plaintext)
220{
221  register long
222    i;
223
224  /*
225    Xor corresponding text input and round key input bytes.
226  */
227  for (i=0; i < 4; i++)
228    plaintext[i]=key[i] ^ ciphertext[i];
229}
230
231static inline unsigned char ByteMultiply(const unsigned char alpha,
232  const unsigned char beta)
233{
234  /*
235    Byte multiply two elements of GF(2^m) (mix columns and inverse mix columns).
236  */
237  if ((alpha == 0) || (beta == 0))
238    return(0);
239  return(InverseLog[(Log[alpha]+Log[beta]) % 0xff]);
240}
241
242static inline unsigned int ByteSubTransform(unsigned int x,
243  unsigned char *s_box)
244{
245  unsigned int
246    key;
247
248  /*
249    Non-linear layer resists differential and linear cryptoanalysis attacks.
250  */
251  key=(s_box[x & 0xff]) | (s_box[(x >> 8) & 0xff] << 8) |
252    (s_box[(x >> 16) & 0xff] << 16) | (s_box[(x >> 24) & 0xff] << 24);
253  return(key);
254}
255
256static void FinalizeRoundKey(const unsigned int *ciphertext,
257  const unsigned int *key,unsigned char *plaintext)
258{
259  register unsigned char
260    *p;
261
262  register unsigned int
263    i,
264    j;
265
266  unsigned int
267    value;
268
269  /*
270    The round key is XORed with the result of the mix-column transformation.
271  */
272  p=plaintext;
273  for (i=0; i < 4; i++)
274  {
275    value=ciphertext[i] ^ key[i];
276    for (j=0; j < 4; j++)
277      *p++=(value >> (8*j)) & 0xff;
278  }
279  /*
280    Reset registers.
281  */
282  value=0;
283}
284
285static void InitializeRoundKey(const unsigned char *ciphertext,
286  const unsigned int *key,unsigned int *plaintext)
287{
288  register const unsigned char
289    *p;
290
291  register unsigned int
292    i,
293    j;
294
295  unsigned int
296    value;
297
298  p=ciphertext;
299  for (i=0; i < 4; i++)
300  {
301    value=0;
302    for (j=0; j < 4; j++)
303      value|=(*p++ << (8*j));
304    plaintext[i]=key[i] ^ value;
305  }
306  /*
307    Reset registers.
308  */
309  value=0;
310}
311
312static inline unsigned int RotateLeft(const unsigned int x)
313{
314  return(((x << 8) | ((x >> 24) & 0xff)));
315}
316
317WizardExport void DecipherAESBlock(AESInfo *aes_info,
318  const unsigned char *ciphertext,unsigned char *plaintext)
319{
320  static int
321    map[4][4] =
322    {
323      { 0, 1, 2, 3 },
324      { 3, 0, 1, 2 },
325      { 2, 3, 0, 1 },
326      { 1, 2, 3, 0 }
327    };
328
329  static unsigned char
330    InverseSBox[256] =
331    {
332       82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243,
333      215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68,
334      196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,  61, 238,  76,
335      149,  11,  66, 250, 195,  78,   8,  46, 161, 102,  40, 217,  36, 178,
336      118,  91, 162,  73, 109, 139, 209,  37, 114, 248, 246, 100, 134, 104,
337      152,  22, 212, 164,  92, 204,  93, 101, 182, 146, 108, 112,  72,  80,
338      253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132, 144, 216,
339      171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6,
340      208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19,
341      138, 107,  58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206,
342      240, 180, 230, 115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,
343       55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137,
344      111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210,
345      121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,  51,
346      136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81,
347      127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239,
348      160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83,
349      153,  97,  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,
350       85,  33,  12, 125,
351    };
352
353  static unsigned int
354    I[] =
355    {
356      0x50a7f451U, 0x5365417eU, 0xc3a4171aU, 0x965e273aU, 0xcb6bab3bU,
357      0xf1459d1fU, 0xab58faacU, 0x9303e34bU, 0x55fa3020U, 0xf66d76adU,
358      0x9176cc88U, 0x254c02f5U, 0xfcd7e54fU, 0xd7cb2ac5U, 0x80443526U,
359      0x8fa362b5U, 0x495ab1deU, 0x671bba25U, 0x980eea45U, 0xe1c0fe5dU,
360      0x02752fc3U, 0x12f04c81U, 0xa397468dU, 0xc6f9d36bU, 0xe75f8f03U,
361      0x959c9215U, 0xeb7a6dbfU, 0xda595295U, 0x2d83bed4U, 0xd3217458U,
362      0x2969e049U, 0x44c8c98eU, 0x6a89c275U, 0x78798ef4U, 0x6b3e5899U,
363      0xdd71b927U, 0xb64fe1beU, 0x17ad88f0U, 0x66ac20c9U, 0xb43ace7dU,
364      0x184adf63U, 0x82311ae5U, 0x60335197U, 0x457f5362U, 0xe07764b1U,
365      0x84ae6bbbU, 0x1ca081feU, 0x942b08f9U, 0x58684870U, 0x19fd458fU,
366      0x876cde94U, 0xb7f87b52U, 0x23d373abU, 0xe2024b72U, 0x578f1fe3U,
367      0x2aab5566U, 0x0728ebb2U, 0x03c2b52fU, 0x9a7bc586U, 0xa50837d3U,
368      0xf2872830U, 0xb2a5bf23U, 0xba6a0302U, 0x5c8216edU, 0x2b1ccf8aU,
369      0x92b479a7U, 0xf0f207f3U, 0xa1e2694eU, 0xcdf4da65U, 0xd5be0506U,
370      0x1f6234d1U, 0x8afea6c4U, 0x9d532e34U, 0xa055f3a2U, 0x32e18a05U,
371      0x75ebf6a4U, 0x39ec830bU, 0xaaef6040U, 0x069f715eU, 0x51106ebdU,
372      0xf98a213eU, 0x3d06dd96U, 0xae053eddU, 0x46bde64dU, 0xb58d5491U,
373      0x055dc471U, 0x6fd40604U, 0xff155060U, 0x24fb9819U, 0x97e9bdd6U,
374      0xcc434089U, 0x779ed967U, 0xbd42e8b0U, 0x888b8907U, 0x385b19e7U,
375      0xdbeec879U, 0x470a7ca1U, 0xe90f427cU, 0xc91e84f8U, 0x00000000U,
376      0x83868009U, 0x48ed2b32U, 0xac70111eU, 0x4e725a6cU, 0xfbff0efdU,
377      0x5638850fU, 0x1ed5ae3dU, 0x27392d36U, 0x64d90f0aU, 0x21a65c68U,
378      0xd1545b9bU, 0x3a2e3624U, 0xb1670a0cU, 0x0fe75793U, 0xd296eeb4U,
379      0x9e919b1bU, 0x4fc5c080U, 0xa220dc61U, 0x694b775aU, 0x161a121cU,
380      0x0aba93e2U, 0xe52aa0c0U, 0x43e0223cU, 0x1d171b12U, 0x0b0d090eU,
381      0xadc78bf2U, 0xb9a8b62dU, 0xc8a91e14U, 0x8519f157U, 0x4c0775afU,
382      0xbbdd99eeU, 0xfd607fa3U, 0x9f2601f7U, 0xbcf5725cU, 0xc53b6644U,
383      0x347efb5bU, 0x7629438bU, 0xdcc623cbU, 0x68fcedb6U, 0x63f1e4b8U,
384      0xcadc31d7U, 0x10856342U, 0x40229713U, 0x2011c684U, 0x7d244a85U,
385      0xf83dbbd2U, 0x1132f9aeU, 0x6da129c7U, 0x4b2f9e1dU, 0xf330b2dcU,
386      0xec52860dU, 0xd0e3c177U, 0x6c16b32bU, 0x99b970a9U, 0xfa489411U,
387      0x2264e947U, 0xc48cfca8U, 0x1a3ff0a0U, 0xd82c7d56U, 0xef903322U,
388      0xc74e4987U, 0xc1d138d9U, 0xfea2ca8cU, 0x360bd498U, 0xcf81f5a6U,
389      0x28de7aa5U, 0x268eb7daU, 0xa4bfad3fU, 0xe49d3a2cU, 0x0d927850U,
390      0x9bcc5f6aU, 0x62467e54U, 0xc2138df6U, 0xe8b8d890U, 0x5ef7392eU,
391      0xf5afc382U, 0xbe805d9fU, 0x7c93d069U, 0xa92dd56fU, 0xb31225cfU,
392      0x3b99acc8U, 0xa77d1810U, 0x6e639ce8U, 0x7bbb3bdbU, 0x097826cdU,
393      0xf418596eU, 0x01b79aecU, 0xa89a4f83U, 0x656e95e6U, 0x7ee6ffaaU,
394      0x08cfbc21U, 0xe6e815efU, 0xd99be7baU, 0xce366f4aU, 0xd4099feaU,
395      0xd67cb029U, 0xafb2a431U, 0x31233f2aU, 0x3094a5c6U, 0xc066a235U,
396      0x37bc4e74U, 0xa6ca82fcU, 0xb0d090e0U, 0x15d8a733U, 0x4a9804f1U,
397      0xf7daec41U, 0x0e50cd7fU, 0x2ff69117U, 0x8dd64d76U, 0x4db0ef43U,
398      0x544daaccU, 0xdf0496e4U, 0xe3b5d19eU, 0x1b886a4cU, 0xb81f2cc1U,
399      0x7f516546U, 0x04ea5e9dU, 0x5d358c01U, 0x737487faU, 0x2e410bfbU,
400      0x5a1d67b3U, 0x52d2db92U, 0x335610e9U, 0x1347d66dU, 0x8c61d79aU,
401      0x7a0ca137U, 0x8e14f859U, 0x893c13ebU, 0xee27a9ceU, 0x35c961b7U,
402      0xede51ce1U, 0x3cb1477aU, 0x59dfd29cU, 0x3f73f255U, 0x79ce1418U,
403      0xbf37c773U, 0xeacdf753U, 0x5baafd5fU, 0x146f3ddfU, 0x86db4478U,
404      0x81f3afcaU, 0x3ec468b9U, 0x2c342438U, 0x5f40a3c2U, 0x72c31d16U,
405      0x0c25e2bcU, 0x8b493c28U, 0x41950dffU, 0x7101a839U, 0xdeb30c08U,
406      0x9ce4b4d8U, 0x90c15664U, 0x6184cb7bU, 0x70b632d5U, 0x745c6c48U,
407      0x4257b8d0U
408    };
409
410  register long
411    i,
412    j;
413
414  unsigned int
415    alpha,
416    key[4],
417    text[4];
418
419  /*
420    Decipher one block.
421  */
422  (void) memset(text,0,sizeof(text));
423  InitializeRoundKey(ciphertext,aes_info->decipher_key+4*aes_info->rounds,text);
424  for (i=aes_info->rounds-1; i > 0;  i--)
425  {
426    /*
427      This linear mixing step undiffuses the bits over multiple rounds.
428    */
429    for (j=0; j < 4; j++)
430      key[j]=I[text[j] & 0xff] ^
431        RotateLeft(I[(text[map[1][j]] >> 8) & 0xff] ^
432        RotateLeft(I[(text[map[2][j]] >> 16) & 0xff] ^
433        RotateLeft(I[(text[map[3][j]] >> 24) & 0xff])));
434    AddRoundKey(key,aes_info->decipher_key+4*i,text);
435  }
436  for (i=0; i < 4; i++)
437  {
438    alpha=(text[i] & 0x000000ff) | ((text[map[1][i]]) & 0x0000ff00) |
439      ((text[map[2][i]]) & 0x00ff0000) | ((text[map[3][i]]) & 0xff000000);
440    key[i]=ByteSubTransform(alpha,InverseSBox);
441  }
442  FinalizeRoundKey(key,aes_info->decipher_key,plaintext);
443  /*
444    Reset registers.
445  */
446  alpha=0;
447  (void) ResetWizardMemory(key,0,sizeof(key));
448  (void) ResetWizardMemory(text,0,sizeof(text));
449}
450
451/*
452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453%                                                                             %
454%                                                                             %
455%                                                                             %
456%   D e s t r o y A E S I n f o                                               %
457%                                                                             %
458%                                                                             %
459%                                                                             %
460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461%
462%  DestroyAESInfo() zeros memory associated with the AESInfo structure.
463%
464%  The format of the DestroyAESInfo method is:
465%
466%      AESInfo *DestroyAESInfo(AESInfo *aes_info)
467%
468%  A description of each parameter follows:
469%
470%    o aes_info: The cipher context.
471%
472*/
473WizardExport AESInfo *DestroyAESInfo(AESInfo *aes_info)
474{
475  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
476  WizardAssert(CipherDomain,aes_info != (AESInfo *) NULL);
477  WizardAssert(CipherDomain,aes_info->signature == WizardSignature);
478  if (aes_info->decipher_key != (unsigned int *) NULL)
479    aes_info->decipher_key=(unsigned int *)
480      RelinquishWizardMemory(aes_info->decipher_key);
481  if (aes_info->encipher_key != (unsigned int *) NULL)
482    aes_info->encipher_key=(unsigned int *)
483      RelinquishWizardMemory(aes_info->encipher_key);
484  if (aes_info->key != (StringInfo *) NULL)
485    aes_info->key=DestroyStringInfo(aes_info->key);
486  aes_info->signature=(~WizardSignature);
487  aes_info=(AESInfo *) RelinquishWizardMemory(aes_info);
488  return(aes_info);
489}
490
491/*
492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493%                                                                             %
494%                                                                             %
495%                                                                             %
496%   E n c i p h e r A E S B l o c k                                           %
497%                                                                             %
498%                                                                             %
499%                                                                             %
500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501%
502%  EncipherAESBlock() enciphers a single block of plaintext to produce a block
503%  of ciphertext.
504%
505%  The format of the EncipherAESBlock method is:
506%
507%      void EncipherAES(AESInfo *aes_info,const unsigned char *plaintext,
508%        unsigned char *ciphertext)
509%
510%  A description of each parameter follows:
511%
512%    o aes_info: The cipher context.
513%
514%    o plaintext: The plain text.
515%
516%    o ciphertext: The cipher text.
517%
518*/
519WizardExport void EncipherAESBlock(AESInfo *aes_info,
520  const unsigned char *plaintext,unsigned char *ciphertext)
521{
522  register long
523    i,
524    j;
525
526  static int
527    map[4][4] =
528    {
529      { 0, 1, 2, 3 },
530      { 1, 2, 3, 0 },
531      { 2, 3, 0, 1 },
532      { 3, 0, 1, 2 }
533    };
534
535  static unsigned int
536    D[] =
537    {
538      0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U, 0x0df2f2ffU,
539      0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U, 0x50303060U, 0x03010102U,
540      0xa96767ceU, 0x7d2b2b56U, 0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU,
541      0x9a7676ecU, 0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU,
542      0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU, 0xecadad41U,
543      0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U, 0xbf9c9c23U, 0xf7a4a453U,
544      0x967272e4U, 0x5bc0c09bU, 0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU,
545      0x6a26264cU, 0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U,
546      0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U, 0x937171e2U,
547      0x73d8d8abU, 0x53313162U, 0x3f15152aU, 0x0c040408U, 0x52c7c795U,
548      0x65232346U, 0x5ec3c39dU, 0x28181830U, 0xa1969637U, 0x0f05050aU,
549      0xb59a9a2fU, 0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU,
550      0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU, 0x1b090912U,
551      0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U, 0x2d1b1b36U, 0xb26e6edcU,
552      0xee5a5ab4U, 0xfba0a05bU, 0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U,
553      0xceb3b37dU, 0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U,
554      0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U, 0x60202040U,
555      0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U, 0xbe6a6ad4U, 0x46cbcb8dU,
556      0xd9bebe67U, 0x4b393972U, 0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U,
557      0x4acfcf85U, 0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU,
558      0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U, 0xcf45458aU,
559      0x10f9f9e9U, 0x06020204U, 0x817f7ffeU, 0xf05050a0U, 0x443c3c78U,
560      0xba9f9f25U, 0xe3a8a84bU, 0xf35151a2U, 0xfea3a35dU, 0xc0404080U,
561      0x8a8f8f05U, 0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U,
562      0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U, 0x30101020U,
563      0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU, 0x4ccdcd81U, 0x140c0c18U,
564      0x35131326U, 0x2fececc3U, 0xe15f5fbeU, 0xa2979735U, 0xcc444488U,
565      0x3917172eU, 0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU,
566      0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U, 0xa06060c0U,
567      0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U, 0x66222244U, 0x7e2a2a54U,
568      0xab90903bU, 0x8388880bU, 0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU,
569      0x3c141428U, 0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU,
570      0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U, 0xdb494992U,
571      0x0a06060cU, 0x6c242448U, 0xe45c5cb8U, 0x5dc2c29fU, 0x6ed3d3bdU,
572      0xefacac43U, 0xa66262c4U, 0xa8919139U, 0xa4959531U, 0x37e4e4d3U,
573      0x8b7979f2U, 0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU,
574      0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U, 0xb46c6cd8U,
575      0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU, 0xaf6565caU, 0x8e7a7af4U,
576      0xe9aeae47U, 0x18080810U, 0xd5baba6fU, 0x887878f0U, 0x6f25254aU,
577      0x722e2e5cU, 0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U,
578      0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU, 0xdd4b4b96U,
579      0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU, 0x907070e0U, 0x423e3e7cU,
580      0xc4b5b571U, 0xaa6666ccU, 0xd8484890U, 0x05030306U, 0x01f6f6f7U,
581      0x120e0e1cU, 0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U,
582      0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U, 0x38e1e1d9U,
583      0x13f8f8ebU, 0xb398982bU, 0x33111122U, 0xbb6969d2U, 0x70d9d9a9U,
584      0x898e8e07U, 0xa7949433U, 0xb69b9b2dU, 0x221e1e3cU, 0x92878715U,
585      0x20e9e9c9U, 0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U,
586      0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU, 0xdabfbf65U,
587      0x31e6e6d7U, 0xc6424284U, 0xb86868d0U, 0xc3414182U, 0xb0999929U,
588      0x772d2d5aU, 0x110f0f1eU, 0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU,
589      0x3a16162cU
590    };
591
592  unsigned int
593    alpha,
594    key[4],
595    text[4];
596
597  /*
598    Encipher one block.
599  */
600  (void) memset(text,0,sizeof(text));
601  InitializeRoundKey(plaintext,aes_info->encipher_key,text);
602  for (i=1; i < aes_info->rounds; i++)
603  {
604    /*
605      Linear mixing step: cause diffusion of the bits over multiple rounds.
606    */
607    for (j=0; j < 4; j++)
608      key[j]=D[text[j] & 0xff] ^
609        RotateLeft(D[(text[map[1][j]] >> 8) & 0xff] ^
610        RotateLeft(D[(text[map[2][j]] >> 16) & 0xff] ^
611        RotateLeft(D[(text[map[3][j]] >> 24) & 0xff])));
612    AddRoundKey(key,aes_info->encipher_key+4*i,text);
613  }
614  for (i=0; i < 4; i++)
615  {
616    alpha=(text[i] & 0x000000ff) | ((text[map[1][i]]) & 0x0000ff00) |
617      ((text[map[2][i]]) & 0x00ff0000) | ((text[map[3][i]]) & 0xff000000);
618    key[i]=ByteSubTransform(alpha,SBox);
619  }
620  FinalizeRoundKey(key,aes_info->encipher_key+4*aes_info->rounds,ciphertext);
621  /*
622    Reset registers.
623  */
624  alpha=0;
625  (void) ResetWizardMemory(key,0,sizeof(key));
626  (void) ResetWizardMemory(text,0,sizeof(text));
627}
628
629/*
630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631%                                                                             %
632%                                                                             %
633%                                                                             %
634%   G e t A E S B l o c k s i z e                                             %
635%                                                                             %
636%                                                                             %
637%                                                                             %
638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639%
640%  GetAESBlocksize() returns the AES blocksize.
641%
642%  The format of the GetAESBlocksize method is:
643%
644%      unsigned int *GetAESBlocksize(const AESInfo *aes_info)
645%
646%  A description of each parameter follows:
647%
648%    o aes_info: The aes info.
649%
650*/
651WizardExport unsigned int GetAESBlocksize(const AESInfo *aes_info)
652{
653  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
654  WizardAssert(CipherDomain,aes_info != (AESInfo *) NULL);
655  WizardAssert(CipherDomain,aes_info->signature == WizardSignature);
656  return(aes_info->blocksize);
657}
658
659/*
660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661%                                                                             %
662%                                                                             %
663%                                                                             %
664%   S e t A E S K e y                                                         %
665%                                                                             %
666%                                                                             %
667%                                                                             %
668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669%
670%  SetAESKey() sets the key for the AES cipher.  The key length is specified
671%  in bits.  Valid values are 128, 192, or 256 requiring a key buffer length
672%  in bytes of 16, 24, and 32 respectively.
673%
674%  The format of the SetAESKey method is:
675%
676%      SetAESKey(AESInfo *aes_info,const StringInfo *key)
677%
678%  A description of each parameter follows:
679%
680%    o aes_info: The cipher context.
681%
682%    o key: The key.
683%
684*/
685
686static inline void InverseAddRoundKey(const unsigned int *alpha,
687  unsigned int *beta)
688{
689  register unsigned int
690    i,
691    j;
692
693  for (i=0; i < 4; i++)
694  {
695    beta[i]=0;
696    for (j=0; j < 4; j++)
697      beta[i]|=(ByteMultiply(0xe,(alpha[i] >> (8*j)) & 0xff) ^
698        ByteMultiply(0xb,(alpha[i] >> (8*((j+1) % 4))) & 0xff) ^
699        ByteMultiply(0xd,(alpha[i] >> (8*((j+2) % 4))) & 0xff) ^
700        ByteMultiply(0x9,(alpha[i] >> (8*((j+3) % 4))) & 0xff)) << (8*j);
701  }
702}
703
704static inline unsigned int XTime(unsigned char alpha)
705{
706  unsigned char
707    beta;
708
709  beta=(unsigned char) ((alpha & 0x80) != 0 ? 0x1b : 0);
710  alpha<<=1;
711  alpha^=beta;
712  return(alpha);
713}
714
715static inline unsigned int RotateRight(const unsigned int x)
716{
717  return((x >> 8) | ((x & 0xff) << 24));
718}
719
720WizardExport void SetAESKey(AESInfo *aes_info,const StringInfo *key)
721{
722  long
723    bytes,
724    n;
725
726  register long
727    i;
728
729  unsigned char
730    *datum;
731
732  unsigned int
733    alpha,
734    beta;
735
736  /*
737    Determine the number of rounds based on the number of bits in key.
738  */
739  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
740  WizardAssert(CipherDomain,aes_info != (AESInfo *) NULL);
741  WizardAssert(CipherDomain,aes_info->signature == WizardSignature);
742  WizardAssert(CipherDomain,key != (StringInfo *) NULL);
743  n=4;
744  aes_info->rounds=10;
745  if ((8*GetStringInfoLength(key)) >= 256)
746    {
747      n=8;
748      aes_info->rounds=14;
749    }
750  else
751    if ((8*GetStringInfoLength(key)) >= 192)
752      {
753        n=6;
754        aes_info->rounds=12;
755      }
756  /*
757    Generate crypt key.
758  */
759  datum=GetStringInfoDatum(aes_info->key);
760  (void) ResetWizardMemory(datum,0,GetStringInfoLength(aes_info->key));
761  (void) CopyWizardMemory(datum,GetStringInfoDatum(key),
762    Min(GetStringInfoLength(key),GetStringInfoLength(aes_info->key)));
763  for (i=0; i < n; i++)
764    aes_info->encipher_key[i]=datum[4*i] | (datum[4*i+1] << 8) |
765      (datum[4*i+2] << 16) | (datum[4*i+3] << 24);
766  beta=1;
767  bytes=(AESBlocksize/4)*(aes_info->rounds+1);
768  for (i=n; i < bytes; i++)
769  {
770    alpha=aes_info->encipher_key[i-1];
771    if ((i % n) == 0)
772      {
773        alpha=ByteSubTransform(RotateRight(alpha),SBox) ^ beta;
774        beta=XTime((unsigned char) (beta & 0xff));
775      }
776    else
777      if ((n > 6) && ((i % n) == 4))
778        alpha=ByteSubTransform(alpha,SBox);
779    aes_info->encipher_key[i]=aes_info->encipher_key[i-n] ^ alpha;
780  }
781  /*
782    Generate deciphering key (in reverse order).
783  */
784  for (i=0; i < 4; i++)
785  {
786    aes_info->decipher_key[i]=aes_info->encipher_key[i];
787    aes_info->decipher_key[bytes-4+i]=aes_info->encipher_key[bytes-4+i];
788  }
789  for (i=4; i < (bytes-4); i+=4)
790    InverseAddRoundKey(aes_info->encipher_key+i,aes_info->decipher_key+i);
791  /*
792    Reset registers.
793  */
794  datum=GetStringInfoDatum(aes_info->key);
795  (void) ResetWizardMemory(datum,0,GetStringInfoLength(aes_info->key));
796  alpha=0;
797  beta=0;
798}
Note: See TracBrowser for help on using the browser.