blob: 4c28f32e68bc1b1b4967efdcf99f695c32afc279 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% CCCC IIIII PPPP H H EEEEE RRRR %
6% C I P P H H E R R %
7% C I PPPP HHHHH EEE RRRR %
8% C I P H H E R R %
9% CCCC IIIII P H H EEEEE R R %
10% %
11% %
12% MagickCore Cipher Methods %
13% %
14% Software Design %
15% John Cristy %
16% March 2003 %
17% %
18% %
cristy1454be72011-12-19 01:52:48 +000019% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000020% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
27% Unless required by applicable law or agreed to in writing, software %
28% distributed under the License is distributed on an "AS IS" BASIS, %
29% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30% See the License for the specific language governing permissions and %
31% limitations under the License. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35%
36*/
37
38/*
39 Include declarations.
40*/
cristy4c08aed2011-07-01 19:47:50 +000041#include "MagickCore/studio.h"
42#include "MagickCore/cache.h"
43#include "MagickCore/cipher.h"
44#include "MagickCore/exception.h"
45#include "MagickCore/exception-private.h"
46#include "MagickCore/hashmap.h"
47#include "MagickCore/image.h"
48#include "MagickCore/image-private.h"
49#include "MagickCore/list.h"
50#include "MagickCore/memory_.h"
51#include "MagickCore/monitor.h"
52#include "MagickCore/monitor-private.h"
53#include "MagickCore/property.h"
54#include "MagickCore/quantum-private.h"
55#include "MagickCore/registry.h"
56#include "MagickCore/semaphore.h"
57#include "MagickCore/signature-private.h"
58#include "MagickCore/splay-tree.h"
59#include "MagickCore/statistic.h"
60#include "MagickCore/string_.h"
cristy3ed852e2009-09-05 21:47:34 +000061
62#if defined(MAGICKCORE_CIPHER_SUPPORT)
63/*
64 Define declarations.
65*/
66#define AESBlocksize 16
67
68/*
69 Typedef declarations.
70*/
71typedef struct _AESInfo
72{
73 StringInfo
74 *key;
75
76 unsigned int
77 blocksize,
78 *encipher_key,
79 *decipher_key;
80
cristybb503372010-05-27 20:51:26 +000081 ssize_t
cristy3ed852e2009-09-05 21:47:34 +000082 rounds,
83 timestamp;
84
cristybb503372010-05-27 20:51:26 +000085 size_t
cristy3ed852e2009-09-05 21:47:34 +000086 signature;
87} AESInfo;
88
89/*
90 Global declarations.
91*/
92static unsigned char
93 InverseLog[256] =
94 {
95 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248,
96 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10,
97 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190,
98 217, 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204,
99 79, 209, 104, 184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59,
100 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208,
101 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196,
102 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
103 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32,
104 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86,
105 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237,
106 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126,
107 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35,
108 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99,
109 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 69, 207,
110 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
111 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242,
112 13, 23, 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180,
113 199, 82, 246, 1
114 },
115 Log[256] =
116 {
117 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238,
118 223, 3, 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200,
119 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228,
120 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36,
121 18, 240, 130, 69, 53, 147, 218, 142, 150, 143, 219, 189, 54, 208,
122 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, 48,
123 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110,
124 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
125 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115,
126 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213,
127 231, 230, 173, 232, 44, 215, 117, 122, 235, 22, 11, 245, 89, 203,
128 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, 236,
129 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96,
130 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, 151, 178, 135, 144,
131 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, 83, 57,
132 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
133 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153,
134 227, 165, 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128,
135 192, 247, 112, 7,
136 },
137 SBox[256] =
138 {
139 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215,
140 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175,
141 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165,
142 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154,
143 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110,
144 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237,
145 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239,
146 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
147 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255,
148 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61,
149 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238,
150 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92,
151 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213,
152 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46,
153 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
154 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
155 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85,
156 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15,
157 176, 84, 187, 22
158 };
159
160/*
161 Forward declarations.
162*/
163static AESInfo
164 *DestroyAESInfo(AESInfo *);
165
166static void
167 EncipherAESBlock(AESInfo *,const unsigned char *,unsigned char *),
168 SetAESKey(AESInfo *,const StringInfo *);
169
170/*
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172% %
173% %
174% %
175% A c q u i r e A E S I n f o %
176% %
177% %
178% %
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180%
181% AcquireAESInfo() allocate the AESInfo structure.
182%
183% The format of the AcquireAESInfo method is:
184%
185% AESInfo *AcquireAESInfo(void)
186%
187*/
188static AESInfo *AcquireAESInfo(void)
189{
190 AESInfo
191 *aes_info;
192
cristy73bd4a52010-10-05 11:24:23 +0000193 aes_info=(AESInfo *) AcquireMagickMemory(sizeof(*aes_info));
cristy3ed852e2009-09-05 21:47:34 +0000194 if (aes_info == (AESInfo *) NULL)
195 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
196 (void) ResetMagickMemory(aes_info,0,sizeof(*aes_info));
197 aes_info->blocksize=AESBlocksize;
198 aes_info->key=AcquireStringInfo(32);
199 aes_info->encipher_key=(unsigned int *) AcquireQuantumMemory(60UL,sizeof(
200 *aes_info->encipher_key));
201 aes_info->decipher_key=(unsigned int *) AcquireQuantumMemory(60UL,sizeof(
202 *aes_info->decipher_key));
203 if ((aes_info->key == (StringInfo *) NULL) ||
204 (aes_info->encipher_key == (unsigned int *) NULL) ||
205 (aes_info->decipher_key == (unsigned int *) NULL))
206 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000207 aes_info->timestamp=(ssize_t) time(0);
cristy3ed852e2009-09-05 21:47:34 +0000208 aes_info->signature=MagickSignature;
209 return(aes_info);
210}
211
212/*
213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214% %
215% %
216% %
217% D e s t r o y A E S I n f o %
218% %
219% %
220% %
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222%
223% DestroyAESInfo() zeros memory associated with the AESInfo structure.
224%
225% The format of the DestroyAESInfo method is:
226%
227% AESInfo *DestroyAESInfo(AESInfo *aes_info)
228%
229% A description of each parameter follows:
230%
231% o aes_info: the cipher context.
232%
233*/
234static AESInfo *DestroyAESInfo(AESInfo *aes_info)
235{
236 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
237 assert(aes_info != (AESInfo *) NULL);
238 assert(aes_info->signature == MagickSignature);
239 if (aes_info->decipher_key != (unsigned int *) NULL)
240 aes_info->decipher_key=(unsigned int *) RelinquishMagickMemory(
241 aes_info->decipher_key);
242 if (aes_info->encipher_key != (unsigned int *) NULL)
243 aes_info->encipher_key=(unsigned int *) RelinquishMagickMemory(
244 aes_info->encipher_key);
245 if (aes_info->key != (StringInfo *) NULL)
246 aes_info->key=DestroyStringInfo(aes_info->key);
247 aes_info->signature=(~MagickSignature);
248 aes_info=(AESInfo *) RelinquishMagickMemory(aes_info);
249 return(aes_info);
250}
251
252/*
253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254% %
255% %
256% %
257% E n c i p h e r A E S B l o c k %
258% %
259% %
260% %
261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262%
263% EncipherAESBlock() enciphers a single block of plaintext to produce a block
264% of ciphertext.
265%
266% The format of the EncipherAESBlock method is:
267%
268% void EncipherAES(AESInfo *aes_info,const unsigned char *plaintext,
269% unsigned char *ciphertext)
270%
271% A description of each parameter follows:
272%
273% o aes_info: the cipher context.
274%
275% o plaintext: the plain text.
276%
277% o ciphertext: the cipher text.
278%
279*/
280
281static inline void AddRoundKey(const unsigned int *ciphertext,
282 const unsigned int *key,unsigned int *plaintext)
283{
cristybb503372010-05-27 20:51:26 +0000284 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000285 i;
286
287 /*
288 Xor corresponding text input and round key input bytes.
289 */
290 for (i=0; i < 4; i++)
291 plaintext[i]=key[i] ^ ciphertext[i];
292}
293
294static inline unsigned char ByteMultiply(const unsigned char alpha,
295 const unsigned char beta)
296{
297 /*
298 Byte multiply two elements of GF(2^m) (mix columns and inverse mix columns).
299 */
300 if ((alpha == 0) || (beta == 0))
301 return(0);
302 return(InverseLog[(Log[alpha]+Log[beta]) % 0xff]);
303}
304
305static inline unsigned int ByteSubTransform(unsigned int x,
306 unsigned char *s_box)
307{
308 unsigned int
309 key;
310
311 /*
312 Non-linear layer resists differential and linear cryptoanalysis attacks.
313 */
314 key=(s_box[x & 0xff]) | (s_box[(x >> 8) & 0xff] << 8) |
315 (s_box[(x >> 16) & 0xff] << 16) | (s_box[(x >> 24) & 0xff] << 24);
316 return(key);
317}
318
319static void FinalizeRoundKey(const unsigned int *ciphertext,
320 const unsigned int *key,unsigned char *plaintext)
321{
322 register unsigned char
323 *p;
324
325 register unsigned int
326 i,
327 j;
328
329 unsigned int
330 value;
331
332 /*
333 The round key is XORed with the result of the mix-column transformation.
334 */
335 p=plaintext;
336 for (i=0; i < 4; i++)
337 {
338 value=ciphertext[i] ^ key[i];
339 for (j=0; j < 4; j++)
cristyaa83c2c2011-09-21 13:36:25 +0000340 *p++=(unsigned char) ((value >> (8*j)) & 0xff);
cristy3ed852e2009-09-05 21:47:34 +0000341 }
342 /*
343 Reset registers.
344 */
345 value=0;
346}
347
348static void InitializeRoundKey(const unsigned char *ciphertext,
349 const unsigned int *key,unsigned int *plaintext)
350{
351 register const unsigned char
352 *p;
353
354 register unsigned int
355 i,
356 j;
357
358 unsigned int
359 value;
360
361 p=ciphertext;
362 for (i=0; i < 4; i++)
363 {
364 value=0;
365 for (j=0; j < 4; j++)
366 value|=(*p++ << (8*j));
367 plaintext[i]=key[i] ^ value;
368 }
369 /*
370 Reset registers.
371 */
372 value=0;
373}
374
375static inline unsigned int RotateLeft(const unsigned int x)
376{
377 return(((x << 8) | ((x >> 24) & 0xff)));
378}
379
380static void EncipherAESBlock(AESInfo *aes_info,const unsigned char *plaintext,
381 unsigned char *ciphertext)
382{
cristybb503372010-05-27 20:51:26 +0000383 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000384 i,
385 j;
386
387 static int
388 map[4][4] =
389 {
390 { 0, 1, 2, 3 },
391 { 1, 2, 3, 0 },
392 { 2, 3, 0, 1 },
393 { 3, 0, 1, 2 }
394 };
395
396 static unsigned int
397 D[] =
398 {
399 0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U, 0x0df2f2ffU,
400 0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U, 0x50303060U, 0x03010102U,
401 0xa96767ceU, 0x7d2b2b56U, 0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU,
402 0x9a7676ecU, 0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU,
403 0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU, 0xecadad41U,
404 0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U, 0xbf9c9c23U, 0xf7a4a453U,
405 0x967272e4U, 0x5bc0c09bU, 0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU,
406 0x6a26264cU, 0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U,
407 0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U, 0x937171e2U,
408 0x73d8d8abU, 0x53313162U, 0x3f15152aU, 0x0c040408U, 0x52c7c795U,
409 0x65232346U, 0x5ec3c39dU, 0x28181830U, 0xa1969637U, 0x0f05050aU,
410 0xb59a9a2fU, 0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU,
411 0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU, 0x1b090912U,
412 0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U, 0x2d1b1b36U, 0xb26e6edcU,
413 0xee5a5ab4U, 0xfba0a05bU, 0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U,
414 0xceb3b37dU, 0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U,
415 0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U, 0x60202040U,
416 0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U, 0xbe6a6ad4U, 0x46cbcb8dU,
417 0xd9bebe67U, 0x4b393972U, 0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U,
418 0x4acfcf85U, 0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU,
419 0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U, 0xcf45458aU,
420 0x10f9f9e9U, 0x06020204U, 0x817f7ffeU, 0xf05050a0U, 0x443c3c78U,
421 0xba9f9f25U, 0xe3a8a84bU, 0xf35151a2U, 0xfea3a35dU, 0xc0404080U,
422 0x8a8f8f05U, 0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U,
423 0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U, 0x30101020U,
424 0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU, 0x4ccdcd81U, 0x140c0c18U,
425 0x35131326U, 0x2fececc3U, 0xe15f5fbeU, 0xa2979735U, 0xcc444488U,
426 0x3917172eU, 0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU,
427 0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U, 0xa06060c0U,
428 0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U, 0x66222244U, 0x7e2a2a54U,
429 0xab90903bU, 0x8388880bU, 0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU,
430 0x3c141428U, 0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU,
431 0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U, 0xdb494992U,
432 0x0a06060cU, 0x6c242448U, 0xe45c5cb8U, 0x5dc2c29fU, 0x6ed3d3bdU,
433 0xefacac43U, 0xa66262c4U, 0xa8919139U, 0xa4959531U, 0x37e4e4d3U,
434 0x8b7979f2U, 0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU,
435 0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U, 0xb46c6cd8U,
436 0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU, 0xaf6565caU, 0x8e7a7af4U,
437 0xe9aeae47U, 0x18080810U, 0xd5baba6fU, 0x887878f0U, 0x6f25254aU,
438 0x722e2e5cU, 0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U,
439 0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU, 0xdd4b4b96U,
440 0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU, 0x907070e0U, 0x423e3e7cU,
441 0xc4b5b571U, 0xaa6666ccU, 0xd8484890U, 0x05030306U, 0x01f6f6f7U,
442 0x120e0e1cU, 0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U,
443 0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U, 0x38e1e1d9U,
444 0x13f8f8ebU, 0xb398982bU, 0x33111122U, 0xbb6969d2U, 0x70d9d9a9U,
445 0x898e8e07U, 0xa7949433U, 0xb69b9b2dU, 0x221e1e3cU, 0x92878715U,
446 0x20e9e9c9U, 0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U,
447 0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU, 0xdabfbf65U,
448 0x31e6e6d7U, 0xc6424284U, 0xb86868d0U, 0xc3414182U, 0xb0999929U,
449 0x772d2d5aU, 0x110f0f1eU, 0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU,
450 0x3a16162cU
451 };
452
453 unsigned int
454 alpha,
455 key[4],
456 text[4];
457
458 /*
459 Encipher one block.
460 */
461 (void) memset(text,0,sizeof(text));
462 InitializeRoundKey(plaintext,aes_info->encipher_key,text);
463 for (i=1; i < aes_info->rounds; i++)
464 {
465 /*
466 Linear mixing step: cause diffusion of the bits over multiple rounds.
467 */
468 for (j=0; j < 4; j++)
469 key[j]=D[text[j] & 0xff] ^
470 RotateLeft(D[(text[map[1][j]] >> 8) & 0xff] ^
471 RotateLeft(D[(text[map[2][j]] >> 16) & 0xff] ^
472 RotateLeft(D[(text[map[3][j]] >> 24) & 0xff])));
473 AddRoundKey(key,aes_info->encipher_key+4*i,text);
474 }
475 for (i=0; i < 4; i++)
476 {
477 alpha=(text[i] & 0x000000ff) | ((text[map[1][i]]) & 0x0000ff00) |
478 ((text[map[2][i]]) & 0x00ff0000) | ((text[map[3][i]]) & 0xff000000);
479 key[i]=ByteSubTransform(alpha,SBox);
480 }
481 FinalizeRoundKey(key,aes_info->encipher_key+4*aes_info->rounds,ciphertext);
482 /*
483 Reset registers.
484 */
485 alpha=0;
486 (void) ResetMagickMemory(key,0,sizeof(key));
487 (void) ResetMagickMemory(text,0,sizeof(text));
488}
489
490/*
491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492% %
493% %
494% %
495% P a s s k e y D e c i p h e r I m a g e %
496% %
497% %
498% %
499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500%
501% PasskeyDecipherImage() converts cipher pixels to plain pixels.
502%
503% The format of the PasskeyDecipherImage method is:
504%
505% MagickBooleanType PasskeyDecipherImage(Image *image,
506% const StringInfo *passkey,ExceptionInfo *exception)
507% MagickBooleanType DecipherImage(Image *image,const char *passphrase,
508% ExceptionInfo *exception)
509%
510% A description of each parameter follows:
511%
512% o image: the image.
513%
514% o passphrase: decipher cipher pixels with this passphrase.
515%
516% o passkey: decrypt cipher pixels with this passkey.
517%
518% o exception: return any errors or warnings in this structure.
519%
520*/
521
cristy0b1cd152012-06-11 17:51:18 +0000522static inline void IncrementCipherNonce(const size_t length,
523 unsigned char *nonce)
524{
525 register ssize_t
526 i;
527
528 for (i=(ssize_t) (length-1); i >= 0; i--)
529 {
530 nonce[i]++;
531 if (nonce[i] != 0)
532 return;
533 }
534 ThrowFatalException(ResourceLimitFatalError,"Sequence wrap error `%s'");
535}
536
cristy3ed852e2009-09-05 21:47:34 +0000537static inline size_t MagickMin(const size_t x,const size_t y)
538{
539 if (x < y)
540 return(x);
541 return(y);
542}
543
544MagickExport MagickBooleanType DecipherImage(Image *image,
545 const char *passphrase,ExceptionInfo *exception)
546{
547 MagickBooleanType
548 status;
549
550 StringInfo
551 *passkey;
552
553 if (passphrase == (const char *) NULL)
554 return(MagickTrue);
555 passkey=StringToStringInfo(passphrase);
556 if (passkey == (StringInfo *) NULL)
557 return(MagickFalse);
558 status=PasskeyDecipherImage(image,passkey,exception);
559 passkey=DestroyStringInfo(passkey);
560 return(status);
561}
562
563MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
564 const StringInfo *passkey,ExceptionInfo *exception)
565{
566#define DecipherImageTag "Decipher/Image "
567
568 AESInfo
569 *aes_info;
570
cristyc4c8d132010-01-07 01:58:38 +0000571 CacheView
572 *image_view;
573
cristy3ed852e2009-09-05 21:47:34 +0000574 const unsigned char
575 *digest;
576
cristy3ed852e2009-09-05 21:47:34 +0000577 MagickBooleanType
578 proceed;
579
cristy0b1cd152012-06-11 17:51:18 +0000580 MagickSizeType
581 extent;
582
cristy3ed852e2009-09-05 21:47:34 +0000583 QuantumInfo
584 *quantum_info;
585
586 QuantumType
587 quantum_type;
588
589 SignatureInfo
590 *signature_info;
591
592 register unsigned char
593 *p;
594
595 size_t
596 length;
597
cristy9d314ff2011-03-09 01:30:28 +0000598 ssize_t
599 y;
600
cristy3ed852e2009-09-05 21:47:34 +0000601 StringInfo
602 *key,
603 *nonce;
604
605 unsigned char
606 input_block[AESBlocksize],
607 output_block[AESBlocksize],
608 *pixels;
609
cristy3ed852e2009-09-05 21:47:34 +0000610 /*
611 Generate decipher key and nonce.
612 */
613 assert(image != (Image *) NULL);
614 assert(image->signature == MagickSignature);
615 if (image->debug != MagickFalse)
616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
617 assert(exception != (ExceptionInfo *) NULL);
618 assert(exception->signature == MagickSignature);
619 if (passkey == (const StringInfo *) NULL)
620 return(MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +0000621 aes_info=AcquireAESInfo();
622 key=CloneStringInfo(passkey);
623 if (key == (StringInfo *) NULL)
624 {
625 aes_info=DestroyAESInfo(aes_info);
cristy3ed852e2009-09-05 21:47:34 +0000626 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
627 image->filename);
628 }
cristyf6240ac2012-06-11 11:08:33 +0000629 nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
cristy3ed852e2009-09-05 21:47:34 +0000630 if (nonce == (StringInfo *) NULL)
631 {
632 key=DestroyStringInfo(key);
633 aes_info=DestroyAESInfo(aes_info);
cristy3ed852e2009-09-05 21:47:34 +0000634 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
635 image->filename);
636 }
cristyf6240ac2012-06-11 11:08:33 +0000637 SetAESKey(aes_info,key);
638 key=DestroyStringInfo(key);
cristy3ed852e2009-09-05 21:47:34 +0000639 signature_info=AcquireSignatureInfo();
cristyf6240ac2012-06-11 11:08:33 +0000640 UpdateSignature(signature_info,nonce);
cristy0b1cd152012-06-11 17:51:18 +0000641 extent=(MagickSizeType) image->columns*image->rows;
642 SetStringInfoLength(nonce,sizeof(extent));
643 SetStringInfoDatum(nonce,(const unsigned char *) &extent);
cristy3ed852e2009-09-05 21:47:34 +0000644 UpdateSignature(signature_info,nonce);
cristy0b1cd152012-06-11 17:51:18 +0000645 nonce=DestroyStringInfo(nonce);
cristy3ed852e2009-09-05 21:47:34 +0000646 FinalizeSignature(signature_info);
647 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
648 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
649 (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
650 GetSignatureDigestsize(signature_info))*sizeof(*input_block));
cristy3ed852e2009-09-05 21:47:34 +0000651 signature_info=DestroySignatureInfo(signature_info);
652 /*
653 Convert cipher pixels to plain pixels.
654 */
cristy0b1cd152012-06-11 17:51:18 +0000655 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
656 if (quantum_info == (QuantumInfo *) NULL)
657 {
658 aes_info=DestroyAESInfo(aes_info);
659 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
660 image->filename);
661 }
cristy3ed852e2009-09-05 21:47:34 +0000662 quantum_type=GetQuantumType(image,exception);
663 pixels=GetQuantumPixels(quantum_info);
cristydb070952012-04-20 14:33:00 +0000664 image_view=AcquireAuthenticCacheView(image,exception);
cristybb503372010-05-27 20:51:26 +0000665 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000666 {
cristybb503372010-05-27 20:51:26 +0000667 register ssize_t
cristy0b1cd152012-06-11 17:51:18 +0000668 i,
cristy3ed852e2009-09-05 21:47:34 +0000669 x;
670
cristy4c08aed2011-07-01 19:47:50 +0000671 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000672 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000673
674 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000675 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000676 break;
cristy3ed852e2009-09-05 21:47:34 +0000677 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
678 pixels,exception);
679 p=pixels;
cristy0b1cd152012-06-11 17:51:18 +0000680 for (x=0; x < (ssize_t) length; x+=AESBlocksize)
cristy3ed852e2009-09-05 21:47:34 +0000681 {
682 (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
683 sizeof(*output_block));
cristy0b1cd152012-06-11 17:51:18 +0000684 IncrementCipherNonce(AESBlocksize,input_block);
cristy3ed852e2009-09-05 21:47:34 +0000685 EncipherAESBlock(aes_info,output_block,output_block);
cristy0b1cd152012-06-11 17:51:18 +0000686 for (i=0; i < AESBlocksize; i++)
687 p[i]^=output_block[i];
688 p+=AESBlocksize;
689 }
690 (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
691 sizeof(*output_block));
692 EncipherAESBlock(aes_info,output_block,output_block);
cristyd9ecd042012-06-17 18:26:12 +0000693 for (i=0; x < (ssize_t) length; x++)
cristy0b1cd152012-06-11 17:51:18 +0000694 {
695 p[i]^=output_block[i];
696 i++;
cristy3ed852e2009-09-05 21:47:34 +0000697 }
698 (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
699 pixels,exception);
700 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
701 break;
cristybb503372010-05-27 20:51:26 +0000702 proceed=SetImageProgress(image,DecipherImageTag,(MagickOffsetType) y,
703 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000704 if (proceed == MagickFalse)
705 break;
706 }
707 image_view=DestroyCacheView(image_view);
708 (void) DeleteImageProperty(image,"cipher:type");
709 (void) DeleteImageProperty(image,"cipher:mode");
710 (void) DeleteImageProperty(image,"cipher:nonce");
711 image->taint=MagickFalse;
712 /*
713 Free resources.
714 */
715 quantum_info=DestroyQuantumInfo(quantum_info);
716 aes_info=DestroyAESInfo(aes_info);
717 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
718 (void) ResetMagickMemory(output_block,0,sizeof(output_block));
cristybb503372010-05-27 20:51:26 +0000719 return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000720}
721
722/*
723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724% %
725% %
726% %
727% P a s s k e y E n c i p h e r I m a g e %
728% %
729% %
730% %
731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732%
733% PasskeyEncipherImage() converts pixels to cipher-pixels.
734%
735% The format of the PasskeyEncipherImage method is:
736%
737% MagickBooleanType PasskeyEncipherImage(Image *image,
738% const StringInfo *passkey,ExceptionInfo *exception)
739% MagickBooleanType EncipherImage(Image *image,const char *passphrase,
740% ExceptionInfo *exception)
741%
742% A description of each parameter follows:
743%
744% o image: the image.
745%
746% o passphrase: encipher pixels with this passphrase.
747%
748% o passkey: decrypt cipher pixels with this passkey.
749%
750% o exception: return any errors or warnings in this structure.
751%
752*/
753
754MagickExport MagickBooleanType EncipherImage(Image *image,
755 const char *passphrase,ExceptionInfo *exception)
756{
757 MagickBooleanType
758 status;
759
760 StringInfo
761 *passkey;
762
763 if (passphrase == (const char *) NULL)
764 return(MagickTrue);
765 passkey=StringToStringInfo(passphrase);
766 if (passkey == (StringInfo *) NULL)
767 return(MagickFalse);
768 status=PasskeyEncipherImage(image,passkey,exception);
769 passkey=DestroyStringInfo(passkey);
770 return(status);
771}
772
773MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
774 const StringInfo *passkey,ExceptionInfo *exception)
775{
776#define EncipherImageTag "Encipher/Image "
777
778 AESInfo
779 *aes_info;
780
cristyc4c8d132010-01-07 01:58:38 +0000781 CacheView
782 *image_view;
783
cristy3ed852e2009-09-05 21:47:34 +0000784 char
785 *signature;
786
787 const unsigned char
788 *digest;
789
cristy3ed852e2009-09-05 21:47:34 +0000790 MagickBooleanType
791 proceed;
792
cristy0b1cd152012-06-11 17:51:18 +0000793 MagickSizeType
794 extent;
795
cristy3ed852e2009-09-05 21:47:34 +0000796 QuantumInfo
797 *quantum_info;
798
799 QuantumType
800 quantum_type;
801
802 register unsigned char
803 *p;
804
805 SignatureInfo
806 *signature_info;
807
808 size_t
809 length;
810
cristy9d314ff2011-03-09 01:30:28 +0000811 ssize_t
812 y;
813
cristy3ed852e2009-09-05 21:47:34 +0000814 StringInfo
815 *key,
816 *nonce;
817
818 unsigned char
819 input_block[AESBlocksize],
820 output_block[AESBlocksize],
821 *pixels;
822
cristy3ed852e2009-09-05 21:47:34 +0000823 /*
824 Generate encipher key and nonce.
825 */
826 assert(image != (Image *) NULL);
827 assert(image->signature == MagickSignature);
828 if (image->debug != MagickFalse)
829 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
830 assert(exception != (ExceptionInfo *) NULL);
831 assert(exception->signature == MagickSignature);
832 if (passkey == (const StringInfo *) NULL)
833 return(MagickTrue);
cristy574cc262011-08-05 01:23:58 +0000834 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000835 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000836 aes_info=AcquireAESInfo();
837 key=CloneStringInfo(passkey);
838 if (key == (StringInfo *) NULL)
839 {
840 aes_info=DestroyAESInfo(aes_info);
cristy3ed852e2009-09-05 21:47:34 +0000841 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
842 image->filename);
843 }
cristyf6240ac2012-06-11 11:08:33 +0000844 nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
cristy3ed852e2009-09-05 21:47:34 +0000845 if (nonce == (StringInfo *) NULL)
846 {
847 key=DestroyStringInfo(key);
848 aes_info=DestroyAESInfo(aes_info);
cristy3ed852e2009-09-05 21:47:34 +0000849 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
850 image->filename);
851 }
cristyf6240ac2012-06-11 11:08:33 +0000852 SetAESKey(aes_info,key);
853 key=DestroyStringInfo(key);
cristy3ed852e2009-09-05 21:47:34 +0000854 signature_info=AcquireSignatureInfo();
cristyf6240ac2012-06-11 11:08:33 +0000855 UpdateSignature(signature_info,nonce);
cristy0b1cd152012-06-11 17:51:18 +0000856 extent=(MagickSizeType) image->columns*image->rows;
857 SetStringInfoLength(nonce,sizeof(extent));
858 SetStringInfoDatum(nonce,(const unsigned char *) &extent);
cristy3ed852e2009-09-05 21:47:34 +0000859 UpdateSignature(signature_info,nonce);
860 nonce=DestroyStringInfo(nonce);
861 FinalizeSignature(signature_info);
cristy0b1cd152012-06-11 17:51:18 +0000862 signature=StringInfoToHexString(GetSignatureDigest(signature_info));
863 (void) SetImageProperty(image,"cipher:type","AES",exception);
864 (void) SetImageProperty(image,"cipher:mode","CTR",exception);
865 (void) SetImageProperty(image,"cipher:nonce",signature,exception);
866 signature=DestroyString(signature);
cristy3ed852e2009-09-05 21:47:34 +0000867 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
868 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
869 (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
870 GetSignatureDigestsize(signature_info))*sizeof(*input_block));
cristy3ed852e2009-09-05 21:47:34 +0000871 signature_info=DestroySignatureInfo(signature_info);
872 /*
873 Convert plain pixels to cipher pixels.
874 */
cristy0b1cd152012-06-11 17:51:18 +0000875 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
876 if (quantum_info == (QuantumInfo *) NULL)
877 {
878 aes_info=DestroyAESInfo(aes_info);
879 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
880 image->filename);
881 }
cristy3ed852e2009-09-05 21:47:34 +0000882 quantum_type=GetQuantumType(image,exception);
883 pixels=GetQuantumPixels(quantum_info);
cristydb070952012-04-20 14:33:00 +0000884 image_view=AcquireAuthenticCacheView(image,exception);
cristybb503372010-05-27 20:51:26 +0000885 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000886 {
cristybb503372010-05-27 20:51:26 +0000887 register ssize_t
cristy0b1cd152012-06-11 17:51:18 +0000888 i,
cristy3ed852e2009-09-05 21:47:34 +0000889 x;
890
cristy4c08aed2011-07-01 19:47:50 +0000891 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000892 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000893
894 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000895 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000896 break;
cristy3ed852e2009-09-05 21:47:34 +0000897 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
898 pixels,exception);
899 p=pixels;
cristy0b1cd152012-06-11 17:51:18 +0000900 for (x=0; x < (ssize_t) length; x+=AESBlocksize)
cristy3ed852e2009-09-05 21:47:34 +0000901 {
902 (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
903 sizeof(*output_block));
cristy0b1cd152012-06-11 17:51:18 +0000904 IncrementCipherNonce(AESBlocksize,input_block);
cristy3ed852e2009-09-05 21:47:34 +0000905 EncipherAESBlock(aes_info,output_block,output_block);
cristy0b1cd152012-06-11 17:51:18 +0000906 for (i=0; i < AESBlocksize; i++)
907 p[i]^=output_block[i];
908 p+=AESBlocksize;
909 }
910 (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
911 sizeof(*output_block));
912 EncipherAESBlock(aes_info,output_block,output_block);
cristyd9ecd042012-06-17 18:26:12 +0000913 for (i=0; x < (ssize_t) length; x++)
cristy0b1cd152012-06-11 17:51:18 +0000914 {
915 p[i]^=output_block[i];
916 i++;
cristy3ed852e2009-09-05 21:47:34 +0000917 }
918 (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
919 pixels,exception);
920 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
921 break;
cristybb503372010-05-27 20:51:26 +0000922 proceed=SetImageProgress(image,EncipherImageTag,(MagickOffsetType) y,
923 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000924 if (proceed == MagickFalse)
925 break;
926 }
927 image_view=DestroyCacheView(image_view);
928 image->taint=MagickFalse;
929 /*
930 Free resources.
931 */
932 quantum_info=DestroyQuantumInfo(quantum_info);
933 aes_info=DestroyAESInfo(aes_info);
934 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
935 (void) ResetMagickMemory(output_block,0,sizeof(output_block));
cristybb503372010-05-27 20:51:26 +0000936 return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000937}
938
939/*
940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
941% %
942% %
943% %
944% S e t A E S K e y %
945% %
946% %
947% %
948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
949%
950% SetAESKey() sets the key for the AES cipher. The key length is specified
951% in bits. Valid values are 128, 192, or 256 requiring a key buffer length
952% in bytes of 16, 24, and 32 respectively.
953%
954% The format of the SetAESKey method is:
955%
956% SetAESKey(AESInfo *aes_info,const StringInfo *key)
957%
958% A description of each parameter follows:
959%
960% o aes_info: the cipher context.
961%
962% o key: the key.
963%
964*/
965
966static inline void InverseAddRoundKey(const unsigned int *alpha,
967 unsigned int *beta)
968{
969 register unsigned int
970 i,
971 j;
972
973 for (i=0; i < 4; i++)
974 {
975 beta[i]=0;
976 for (j=0; j < 4; j++)
977 beta[i]|=(ByteMultiply(0xe,(alpha[i] >> (8*j)) & 0xff) ^
978 ByteMultiply(0xb,(alpha[i] >> (8*((j+1) % 4))) & 0xff) ^
979 ByteMultiply(0xd,(alpha[i] >> (8*((j+2) % 4))) & 0xff) ^
980 ByteMultiply(0x9,(alpha[i] >> (8*((j+3) % 4))) & 0xff)) << (8*j);
981 }
982}
983
984static inline unsigned int XTime(unsigned char alpha)
985{
986 unsigned char
987 beta;
988
989 beta=(unsigned char) ((alpha & 0x80) != 0 ? 0x1b : 0);
990 alpha<<=1;
991 alpha^=beta;
992 return(alpha);
993}
994
995static inline unsigned int RotateRight(const unsigned int x)
996{
997 return((x >> 8) | ((x & 0xff) << 24));
998}
999
1000static void SetAESKey(AESInfo *aes_info,const StringInfo *key)
1001{
cristy9d314ff2011-03-09 01:30:28 +00001002 register ssize_t
1003 i;
1004
cristybb503372010-05-27 20:51:26 +00001005 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001006 bytes,
1007 n;
1008
cristy3ed852e2009-09-05 21:47:34 +00001009 unsigned char
1010 *datum;
1011
1012 unsigned int
1013 alpha,
1014 beta;
1015
1016 /*
1017 Determine the number of rounds based on the number of bits in key.
1018 */
1019 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1020 assert(aes_info != (AESInfo *) NULL);
1021 assert(aes_info->signature == MagickSignature);
1022 assert(key != (StringInfo *) NULL);
1023 n=4;
1024 aes_info->rounds=10;
1025 if ((8*GetStringInfoLength(key)) >= 256)
1026 {
1027 n=8;
1028 aes_info->rounds=14;
1029 }
1030 else
1031 if ((8*GetStringInfoLength(key)) >= 192)
1032 {
1033 n=6;
1034 aes_info->rounds=12;
1035 }
1036 /*
1037 Generate crypt key.
1038 */
1039 datum=GetStringInfoDatum(aes_info->key);
1040 (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1041 (void) CopyMagickMemory(datum,GetStringInfoDatum(key),MagickMin(
1042 GetStringInfoLength(key),GetStringInfoLength(aes_info->key)));
1043 for (i=0; i < n; i++)
1044 aes_info->encipher_key[i]=datum[4*i] | (datum[4*i+1] << 8) |
1045 (datum[4*i+2] << 16) | (datum[4*i+3] << 24);
1046 beta=1;
1047 bytes=(AESBlocksize/4)*(aes_info->rounds+1);
1048 for (i=n; i < bytes; i++)
1049 {
1050 alpha=aes_info->encipher_key[i-1];
1051 if ((i % n) == 0)
1052 {
1053 alpha=ByteSubTransform(RotateRight(alpha),SBox) ^ beta;
1054 beta=XTime((unsigned char) (beta & 0xff));
1055 }
1056 else
1057 if ((n > 6) && ((i % n) == 4))
1058 alpha=ByteSubTransform(alpha,SBox);
1059 aes_info->encipher_key[i]=aes_info->encipher_key[i-n] ^ alpha;
1060 }
1061 /*
1062 Generate deciper key (in reverse order).
1063 */
1064 for (i=0; i < 4; i++)
1065 {
1066 aes_info->decipher_key[i]=aes_info->encipher_key[i];
1067 aes_info->decipher_key[bytes-4+i]=aes_info->encipher_key[bytes-4+i];
1068 }
1069 for (i=4; i < (bytes-4); i+=4)
1070 InverseAddRoundKey(aes_info->encipher_key+i,aes_info->decipher_key+i);
1071 /*
1072 Reset registers.
1073 */
1074 datum=GetStringInfoDatum(aes_info->key);
1075 (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1076 alpha=0;
1077 beta=0;
1078}
1079#else
1080
1081/*
1082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083% %
1084% %
1085% %
1086% P a s s k e y D e c i p h e r I m a g e %
1087% %
1088% %
1089% %
1090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091%
1092% PasskeyDecipherImage() converts cipher pixels to plain pixels.
1093%
1094% The format of the PasskeyDecipherImage method is:
1095%
1096% MagickBooleanType PasskeyDecipherImage(Image *image,
1097% const StringInfo *passkey,ExceptionInfo *exception)
1098% MagickBooleanType DecipherImage(Image *image,const char *passphrase,
1099% ExceptionInfo *exception)
1100%
1101% A description of each parameter follows:
1102%
1103% o image: the image.
1104%
1105% o passphrase: decipher cipher pixels with this passphrase.
1106%
1107% o passkey: decrypt cipher pixels with this passkey.
1108%
1109% o exception: return any errors or warnings in this structure.
1110%
1111*/
1112
1113MagickExport MagickBooleanType DecipherImage(Image *image,
1114 const char *passphrase,ExceptionInfo *exception)
1115{
1116 assert(image != (Image *) NULL);
1117 assert(image->signature == MagickSignature);
1118 if (image->debug != MagickFalse)
1119 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1120 assert(exception != (ExceptionInfo *) NULL);
1121 assert(exception->signature == MagickSignature);
1122 (void) passphrase;
1123 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1124}
1125
1126MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
1127 const StringInfo *passkey,ExceptionInfo *exception)
1128{
1129 assert(image != (Image *) NULL);
1130 assert(image->signature == MagickSignature);
1131 if (image->debug != MagickFalse)
1132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1133 assert(exception != (ExceptionInfo *) NULL);
1134 assert(exception->signature == MagickSignature);
1135 (void) passkey;
1136 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1137}
1138
1139/*
1140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1141% %
1142% %
1143% %
1144% P a s s k e y E n c i p h e r I m a g e %
1145% %
1146% %
1147% %
1148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1149%
1150% PasskeyEncipherImage() converts pixels to cipher-pixels.
1151%
1152% The format of the PasskeyEncipherImage method is:
1153%
1154% MagickBooleanType PasskeyEncipherImage(Image *image,
1155% const StringInfo *passkey,ExceptionInfo *exception)
1156% MagickBooleanType EncipherImage(Image *image,const char *passphrase,
1157% ExceptionInfo *exception)
1158%
1159% A description of each parameter follows:
1160%
1161% o passphrase: decipher cipher pixels with this passphrase.
1162%
1163% o passkey: decrypt cipher pixels with this passkey.
1164%
1165% o exception: return any errors or warnings in this structure.
1166%
1167*/
1168
1169MagickExport MagickBooleanType EncipherImage(Image *image,
1170 const char *passphrase,ExceptionInfo *exception)
1171{
1172 assert(image != (Image *) NULL);
1173 assert(image->signature == MagickSignature);
1174 if (image->debug != MagickFalse)
1175 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1176 assert(exception != (ExceptionInfo *) NULL);
1177 assert(exception->signature == MagickSignature);
1178 (void) passphrase;
1179 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1180}
1181
1182MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
1183 const StringInfo *passkey,ExceptionInfo *exception)
1184{
1185 assert(image != (Image *) NULL);
1186 assert(image->signature == MagickSignature);
1187 if (image->debug != MagickFalse)
1188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1189 assert(exception != (ExceptionInfo *) NULL);
1190 assert(exception->signature == MagickSignature);
1191 (void) passkey;
1192 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1193}
1194#endif