blob: f1ad73cad43ad0c01853c6a1a4d1aeeb65ef7732 [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% %
cristy16af1cb2009-12-11 21:38:29 +000019% Copyright 1999-2010 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*/
41#include "magick/studio.h"
42#include "magick/cache.h"
43#include "magick/cipher.h"
44#include "magick/exception.h"
45#include "magick/exception-private.h"
46#include "magick/hashmap.h"
47#include "magick/image.h"
48#include "magick/image-private.h"
49#include "magick/list.h"
50#include "magick/memory_.h"
51#include "magick/monitor.h"
52#include "magick/monitor-private.h"
53#include "magick/property.h"
54#include "magick/quantum-private.h"
55#include "magick/registry.h"
56#include "magick/semaphore.h"
57#include "magick/signature-private.h"
58#include "magick/splay-tree.h"
59#include "magick/statistic.h"
60#include "magick/string_.h"
61
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
81 long
82 rounds,
83 timestamp;
84
85 unsigned long
86 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
cristy90823212009-12-12 20:48:33 +0000193 aes_info=(AESInfo *) AcquireAlignedMemory(1,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");
207 aes_info->timestamp=(long) time(0);
208 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{
284 register long
285 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++)
340 *p++=(value >> (8*j)) & 0xff;
341 }
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{
383 register long
384 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
522static inline size_t MagickMin(const size_t x,const size_t y)
523{
524 if (x < y)
525 return(x);
526 return(y);
527}
528
529MagickExport MagickBooleanType DecipherImage(Image *image,
530 const char *passphrase,ExceptionInfo *exception)
531{
532 MagickBooleanType
533 status;
534
535 StringInfo
536 *passkey;
537
538 if (passphrase == (const char *) NULL)
539 return(MagickTrue);
540 passkey=StringToStringInfo(passphrase);
541 if (passkey == (StringInfo *) NULL)
542 return(MagickFalse);
543 status=PasskeyDecipherImage(image,passkey,exception);
544 passkey=DestroyStringInfo(passkey);
545 return(status);
546}
547
548MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
549 const StringInfo *passkey,ExceptionInfo *exception)
550{
551#define DecipherImageTag "Decipher/Image "
552
553 AESInfo
554 *aes_info;
555
556 const unsigned char
557 *digest;
558
559 IndexPacket
560 *indexes;
561
562 long
563 y;
564
565 MagickBooleanType
566 proceed;
567
568 QuantumInfo
569 *quantum_info;
570
571 QuantumType
572 quantum_type;
573
574 SignatureInfo
575 *signature_info;
576
577 register unsigned char
578 *p;
579
580 size_t
581 length;
582
583 StringInfo
584 *key,
585 *nonce;
586
587 unsigned char
588 input_block[AESBlocksize],
589 output_block[AESBlocksize],
590 *pixels;
591
592 CacheView
593 *image_view;
594
595 /*
596 Generate decipher key and nonce.
597 */
598 assert(image != (Image *) NULL);
599 assert(image->signature == MagickSignature);
600 if (image->debug != MagickFalse)
601 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
602 assert(exception != (ExceptionInfo *) NULL);
603 assert(exception->signature == MagickSignature);
604 if (passkey == (const StringInfo *) NULL)
605 return(MagickTrue);
606 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
607 if (quantum_info == (QuantumInfo *) NULL)
608 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
609 image->filename);
610 aes_info=AcquireAESInfo();
611 key=CloneStringInfo(passkey);
612 if (key == (StringInfo *) NULL)
613 {
614 aes_info=DestroyAESInfo(aes_info);
615 quantum_info=DestroyQuantumInfo(quantum_info);
616 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
617 image->filename);
618 }
619 nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
620 if (nonce == (StringInfo *) NULL)
621 {
622 key=DestroyStringInfo(key);
623 aes_info=DestroyAESInfo(aes_info);
624 quantum_info=DestroyQuantumInfo(quantum_info);
625 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
626 image->filename);
627 }
628 SetAESKey(aes_info,key);
629 key=DestroyStringInfo(key);
630 signature_info=AcquireSignatureInfo();
631 UpdateSignature(signature_info,nonce);
632 SetStringInfoLength(nonce,sizeof(quantum_info->extent));
633 SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
634 UpdateSignature(signature_info,nonce);
635 FinalizeSignature(signature_info);
636 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
637 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
638 (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
639 GetSignatureDigestsize(signature_info))*sizeof(*input_block));
640 nonce=DestroyStringInfo(nonce);
641 signature_info=DestroySignatureInfo(signature_info);
642 /*
643 Convert cipher pixels to plain pixels.
644 */
645 quantum_type=GetQuantumType(image,exception);
646 pixels=GetQuantumPixels(quantum_info);
647 image_view=AcquireCacheView(image);
648 for (y=0; y < (long) image->rows; y++)
649 {
650 register long
651 x;
652
653 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000654 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000655
656 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
657 if (q == (PixelPacket *) NULL)
658 break;
659 indexes=GetCacheViewAuthenticIndexQueue(image_view);
660 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
661 pixels,exception);
662 p=pixels;
663 for (x=0; x < (long) length; x++)
664 {
665 (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
666 sizeof(*output_block));
667 EncipherAESBlock(aes_info,output_block,output_block);
668 (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
669 sizeof(*input_block));
670 input_block[AESBlocksize-1]=(*p);
671 *p++^=(*output_block);
672 }
673 (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
674 pixels,exception);
675 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
676 break;
677 proceed=SetImageProgress(image,DecipherImageTag,y,image->rows);
678 if (proceed == MagickFalse)
679 break;
680 }
681 image_view=DestroyCacheView(image_view);
682 (void) DeleteImageProperty(image,"cipher:type");
683 (void) DeleteImageProperty(image,"cipher:mode");
684 (void) DeleteImageProperty(image,"cipher:nonce");
685 image->taint=MagickFalse;
686 /*
687 Free resources.
688 */
689 quantum_info=DestroyQuantumInfo(quantum_info);
690 aes_info=DestroyAESInfo(aes_info);
691 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
692 (void) ResetMagickMemory(output_block,0,sizeof(output_block));
693 return(y == (long) image->rows ? MagickTrue : MagickFalse);
694}
695
696/*
697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698% %
699% %
700% %
701% P a s s k e y E n c i p h e r I m a g e %
702% %
703% %
704% %
705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706%
707% PasskeyEncipherImage() converts pixels to cipher-pixels.
708%
709% The format of the PasskeyEncipherImage method is:
710%
711% MagickBooleanType PasskeyEncipherImage(Image *image,
712% const StringInfo *passkey,ExceptionInfo *exception)
713% MagickBooleanType EncipherImage(Image *image,const char *passphrase,
714% ExceptionInfo *exception)
715%
716% A description of each parameter follows:
717%
718% o image: the image.
719%
720% o passphrase: encipher pixels with this passphrase.
721%
722% o passkey: decrypt cipher pixels with this passkey.
723%
724% o exception: return any errors or warnings in this structure.
725%
726*/
727
728MagickExport MagickBooleanType EncipherImage(Image *image,
729 const char *passphrase,ExceptionInfo *exception)
730{
731 MagickBooleanType
732 status;
733
734 StringInfo
735 *passkey;
736
737 if (passphrase == (const char *) NULL)
738 return(MagickTrue);
739 passkey=StringToStringInfo(passphrase);
740 if (passkey == (StringInfo *) NULL)
741 return(MagickFalse);
742 status=PasskeyEncipherImage(image,passkey,exception);
743 passkey=DestroyStringInfo(passkey);
744 return(status);
745}
746
747MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
748 const StringInfo *passkey,ExceptionInfo *exception)
749{
750#define EncipherImageTag "Encipher/Image "
751
752 AESInfo
753 *aes_info;
754
755 char
756 *signature;
757
758 const unsigned char
759 *digest;
760
761 IndexPacket
762 *indexes;
763
764 long
765 y;
766
767 MagickBooleanType
768 proceed;
769
770 QuantumInfo
771 *quantum_info;
772
773 QuantumType
774 quantum_type;
775
776 register unsigned char
777 *p;
778
779 SignatureInfo
780 *signature_info;
781
782 size_t
783 length;
784
785 StringInfo
786 *key,
787 *nonce;
788
789 unsigned char
790 input_block[AESBlocksize],
791 output_block[AESBlocksize],
792 *pixels;
793
794 CacheView
795 *image_view;
796
797 /*
798 Generate encipher key and nonce.
799 */
800 assert(image != (Image *) NULL);
801 assert(image->signature == MagickSignature);
802 if (image->debug != MagickFalse)
803 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
804 assert(exception != (ExceptionInfo *) NULL);
805 assert(exception->signature == MagickSignature);
806 if (passkey == (const StringInfo *) NULL)
807 return(MagickTrue);
808 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
809 return(MagickFalse);
810 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
811 if (quantum_info == (QuantumInfo *) NULL)
812 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
813 image->filename);
814 aes_info=AcquireAESInfo();
815 key=CloneStringInfo(passkey);
816 if (key == (StringInfo *) NULL)
817 {
818 aes_info=DestroyAESInfo(aes_info);
819 quantum_info=DestroyQuantumInfo(quantum_info);
820 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
821 image->filename);
822 }
823 nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
824 if (nonce == (StringInfo *) NULL)
825 {
826 key=DestroyStringInfo(key);
827 aes_info=DestroyAESInfo(aes_info);
828 quantum_info=DestroyQuantumInfo(quantum_info);
829 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
830 image->filename);
831 }
832 SetAESKey(aes_info,key);
833 key=DestroyStringInfo(key);
834 signature_info=AcquireSignatureInfo();
835 UpdateSignature(signature_info,nonce);
836 SetStringInfoLength(nonce,sizeof(quantum_info->extent));
837 SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
838 UpdateSignature(signature_info,nonce);
839 nonce=DestroyStringInfo(nonce);
840 FinalizeSignature(signature_info);
841 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
842 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
843 (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
844 GetSignatureDigestsize(signature_info))*sizeof(*input_block));
845 signature=StringInfoToHexString(GetSignatureDigest(signature_info));
846 (void) SetImageProperty(image,"cipher:type","AES");
847 (void) SetImageProperty(image,"cipher:mode","CFB");
848 (void) SetImageProperty(image,"cipher:nonce",signature);
849 signature=DestroyString(signature);
850 signature_info=DestroySignatureInfo(signature_info);
851 /*
852 Convert plain pixels to cipher pixels.
853 */
854 quantum_type=GetQuantumType(image,exception);
855 pixels=GetQuantumPixels(quantum_info);
856 image_view=AcquireCacheView(image);
857 for (y=0; y < (long) image->rows; y++)
858 {
859 register long
860 x;
861
862 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000863 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000864
865 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
866 if (q == (PixelPacket *) NULL)
867 break;
868 indexes=GetCacheViewAuthenticIndexQueue(image_view);
869 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
870 pixels,exception);
871 p=pixels;
872 for (x=0; x < (long) length; x++)
873 {
874 (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
875 sizeof(*output_block));
876 EncipherAESBlock(aes_info,output_block,output_block);
877 *p^=(*output_block);
878 (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
879 sizeof(*input_block));
880 input_block[AESBlocksize-1]=(*p++);
881 }
882 (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
883 pixels,exception);
884 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
885 break;
886 proceed=SetImageProgress(image,EncipherImageTag,y,image->rows);
887 if (proceed == MagickFalse)
888 break;
889 }
890 image_view=DestroyCacheView(image_view);
891 image->taint=MagickFalse;
892 /*
893 Free resources.
894 */
895 quantum_info=DestroyQuantumInfo(quantum_info);
896 aes_info=DestroyAESInfo(aes_info);
897 (void) ResetMagickMemory(input_block,0,sizeof(input_block));
898 (void) ResetMagickMemory(output_block,0,sizeof(output_block));
899 return(y == (long) image->rows ? MagickTrue : MagickFalse);
900}
901
902/*
903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904% %
905% %
906% %
907% S e t A E S K e y %
908% %
909% %
910% %
911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912%
913% SetAESKey() sets the key for the AES cipher. The key length is specified
914% in bits. Valid values are 128, 192, or 256 requiring a key buffer length
915% in bytes of 16, 24, and 32 respectively.
916%
917% The format of the SetAESKey method is:
918%
919% SetAESKey(AESInfo *aes_info,const StringInfo *key)
920%
921% A description of each parameter follows:
922%
923% o aes_info: the cipher context.
924%
925% o key: the key.
926%
927*/
928
929static inline void InverseAddRoundKey(const unsigned int *alpha,
930 unsigned int *beta)
931{
932 register unsigned int
933 i,
934 j;
935
936 for (i=0; i < 4; i++)
937 {
938 beta[i]=0;
939 for (j=0; j < 4; j++)
940 beta[i]|=(ByteMultiply(0xe,(alpha[i] >> (8*j)) & 0xff) ^
941 ByteMultiply(0xb,(alpha[i] >> (8*((j+1) % 4))) & 0xff) ^
942 ByteMultiply(0xd,(alpha[i] >> (8*((j+2) % 4))) & 0xff) ^
943 ByteMultiply(0x9,(alpha[i] >> (8*((j+3) % 4))) & 0xff)) << (8*j);
944 }
945}
946
947static inline unsigned int XTime(unsigned char alpha)
948{
949 unsigned char
950 beta;
951
952 beta=(unsigned char) ((alpha & 0x80) != 0 ? 0x1b : 0);
953 alpha<<=1;
954 alpha^=beta;
955 return(alpha);
956}
957
958static inline unsigned int RotateRight(const unsigned int x)
959{
960 return((x >> 8) | ((x & 0xff) << 24));
961}
962
963static void SetAESKey(AESInfo *aes_info,const StringInfo *key)
964{
965 long
966 bytes,
967 n;
968
969 register long
970 i;
971
972 unsigned char
973 *datum;
974
975 unsigned int
976 alpha,
977 beta;
978
979 /*
980 Determine the number of rounds based on the number of bits in key.
981 */
982 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
983 assert(aes_info != (AESInfo *) NULL);
984 assert(aes_info->signature == MagickSignature);
985 assert(key != (StringInfo *) NULL);
986 n=4;
987 aes_info->rounds=10;
988 if ((8*GetStringInfoLength(key)) >= 256)
989 {
990 n=8;
991 aes_info->rounds=14;
992 }
993 else
994 if ((8*GetStringInfoLength(key)) >= 192)
995 {
996 n=6;
997 aes_info->rounds=12;
998 }
999 /*
1000 Generate crypt key.
1001 */
1002 datum=GetStringInfoDatum(aes_info->key);
1003 (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1004 (void) CopyMagickMemory(datum,GetStringInfoDatum(key),MagickMin(
1005 GetStringInfoLength(key),GetStringInfoLength(aes_info->key)));
1006 for (i=0; i < n; i++)
1007 aes_info->encipher_key[i]=datum[4*i] | (datum[4*i+1] << 8) |
1008 (datum[4*i+2] << 16) | (datum[4*i+3] << 24);
1009 beta=1;
1010 bytes=(AESBlocksize/4)*(aes_info->rounds+1);
1011 for (i=n; i < bytes; i++)
1012 {
1013 alpha=aes_info->encipher_key[i-1];
1014 if ((i % n) == 0)
1015 {
1016 alpha=ByteSubTransform(RotateRight(alpha),SBox) ^ beta;
1017 beta=XTime((unsigned char) (beta & 0xff));
1018 }
1019 else
1020 if ((n > 6) && ((i % n) == 4))
1021 alpha=ByteSubTransform(alpha,SBox);
1022 aes_info->encipher_key[i]=aes_info->encipher_key[i-n] ^ alpha;
1023 }
1024 /*
1025 Generate deciper key (in reverse order).
1026 */
1027 for (i=0; i < 4; i++)
1028 {
1029 aes_info->decipher_key[i]=aes_info->encipher_key[i];
1030 aes_info->decipher_key[bytes-4+i]=aes_info->encipher_key[bytes-4+i];
1031 }
1032 for (i=4; i < (bytes-4); i+=4)
1033 InverseAddRoundKey(aes_info->encipher_key+i,aes_info->decipher_key+i);
1034 /*
1035 Reset registers.
1036 */
1037 datum=GetStringInfoDatum(aes_info->key);
1038 (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1039 alpha=0;
1040 beta=0;
1041}
1042#else
1043
1044/*
1045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046% %
1047% %
1048% %
1049% P a s s k e y D e c i p h e r I m a g e %
1050% %
1051% %
1052% %
1053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054%
1055% PasskeyDecipherImage() converts cipher pixels to plain pixels.
1056%
1057% The format of the PasskeyDecipherImage method is:
1058%
1059% MagickBooleanType PasskeyDecipherImage(Image *image,
1060% const StringInfo *passkey,ExceptionInfo *exception)
1061% MagickBooleanType DecipherImage(Image *image,const char *passphrase,
1062% ExceptionInfo *exception)
1063%
1064% A description of each parameter follows:
1065%
1066% o image: the image.
1067%
1068% o passphrase: decipher cipher pixels with this passphrase.
1069%
1070% o passkey: decrypt cipher pixels with this passkey.
1071%
1072% o exception: return any errors or warnings in this structure.
1073%
1074*/
1075
1076MagickExport MagickBooleanType DecipherImage(Image *image,
1077 const char *passphrase,ExceptionInfo *exception)
1078{
1079 assert(image != (Image *) NULL);
1080 assert(image->signature == MagickSignature);
1081 if (image->debug != MagickFalse)
1082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1083 assert(exception != (ExceptionInfo *) NULL);
1084 assert(exception->signature == MagickSignature);
1085 (void) passphrase;
1086 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1087}
1088
1089MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
1090 const StringInfo *passkey,ExceptionInfo *exception)
1091{
1092 assert(image != (Image *) NULL);
1093 assert(image->signature == MagickSignature);
1094 if (image->debug != MagickFalse)
1095 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1096 assert(exception != (ExceptionInfo *) NULL);
1097 assert(exception->signature == MagickSignature);
1098 (void) passkey;
1099 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1100}
1101
1102/*
1103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104% %
1105% %
1106% %
1107% P a s s k e y E n c i p h e r I m a g e %
1108% %
1109% %
1110% %
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112%
1113% PasskeyEncipherImage() converts pixels to cipher-pixels.
1114%
1115% The format of the PasskeyEncipherImage method is:
1116%
1117% MagickBooleanType PasskeyEncipherImage(Image *image,
1118% const StringInfo *passkey,ExceptionInfo *exception)
1119% MagickBooleanType EncipherImage(Image *image,const char *passphrase,
1120% ExceptionInfo *exception)
1121%
1122% A description of each parameter follows:
1123%
1124% o passphrase: decipher cipher pixels with this passphrase.
1125%
1126% o passkey: decrypt cipher pixels with this passkey.
1127%
1128% o exception: return any errors or warnings in this structure.
1129%
1130*/
1131
1132MagickExport MagickBooleanType EncipherImage(Image *image,
1133 const char *passphrase,ExceptionInfo *exception)
1134{
1135 assert(image != (Image *) NULL);
1136 assert(image->signature == MagickSignature);
1137 if (image->debug != MagickFalse)
1138 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1139 assert(exception != (ExceptionInfo *) NULL);
1140 assert(exception->signature == MagickSignature);
1141 (void) passphrase;
1142 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1143}
1144
1145MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
1146 const StringInfo *passkey,ExceptionInfo *exception)
1147{
1148 assert(image != (Image *) NULL);
1149 assert(image->signature == MagickSignature);
1150 if (image->debug != MagickFalse)
1151 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1152 assert(exception != (ExceptionInfo *) NULL);
1153 assert(exception->signature == MagickSignature);
1154 (void) passkey;
1155 ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1156}
1157#endif