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