]> granicus.if.org Git - imagemagick/blob - magick/cipher.c
(no commit message)
[imagemagick] / magick / cipher.c
1 /*
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 %                                                                             %
19 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
20 %  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 \f
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 \f
62 #if defined(MAGICKCORE_CIPHER_SUPPORT)
63 /*
64   Define declarations.
65 */
66 #define AESBlocksize 16
67 \f
68 /*
69   Typedef declarations.
70 */
71 typedef struct _AESInfo
72 {
73   StringInfo
74     *key;
75
76   unsigned int
77     blocksize,
78     *encipher_key,
79     *decipher_key;
80
81   ssize_t
82     rounds,
83     timestamp;
84
85   size_t
86     signature;
87 } AESInfo;
88 \f
89 /*
90   Global declarations.
91 */
92 static 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 \f
160 /*
161   Forward declarations.
162 */
163 static AESInfo
164   *DestroyAESInfo(AESInfo *);
165
166 static void
167   EncipherAESBlock(AESInfo *,const unsigned char *,unsigned char *),
168   SetAESKey(AESInfo *,const StringInfo *);
169 \f
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 */
188 static AESInfo *AcquireAESInfo(void)
189 {
190   AESInfo
191     *aes_info;
192
193   aes_info=(AESInfo *) AcquireAlignedMemory(1,sizeof(*aes_info));
194   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=(ssize_t) time(0);
208   aes_info->signature=MagickSignature;
209   return(aes_info);
210 }
211 \f
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 */
234 static 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 \f
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
281 static inline void AddRoundKey(const unsigned int *ciphertext,
282   const unsigned int *key,unsigned int *plaintext)
283 {
284   register ssize_t
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
294 static 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
305 static 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
319 static 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
348 static 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
375 static inline unsigned int RotateLeft(const unsigned int x)
376 {
377   return(((x << 8) | ((x >> 24) & 0xff)));
378 }
379
380 static void EncipherAESBlock(AESInfo *aes_info,const unsigned char *plaintext,
381   unsigned char *ciphertext)
382 {
383   register ssize_t
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 \f
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
522 static 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
529 MagickExport 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
548 MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
549   const StringInfo *passkey,ExceptionInfo *exception)
550 {
551 #define DecipherImageTag  "Decipher/Image "
552
553   AESInfo
554     *aes_info;
555
556   CacheView
557     *image_view;
558
559   const unsigned char
560     *digest;
561
562   IndexPacket
563     *indexes;
564
565   ssize_t
566     y;
567
568   MagickBooleanType
569     proceed;
570
571   QuantumInfo
572     *quantum_info;
573
574   QuantumType
575     quantum_type;
576
577   SignatureInfo
578     *signature_info;
579
580   register unsigned char
581     *p;
582
583   size_t
584     length;
585
586   StringInfo
587     *key,
588     *nonce;
589
590   unsigned char
591     input_block[AESBlocksize],
592     output_block[AESBlocksize],
593     *pixels;
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 < (ssize_t) image->rows; y++)
649   {
650     register ssize_t
651       x;
652
653     register PixelPacket
654       *restrict q;
655
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 < (ssize_t) 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,(MagickOffsetType) y,
678       image->rows);
679     if (proceed == MagickFalse)
680       break;
681   }
682   image_view=DestroyCacheView(image_view);
683   (void) DeleteImageProperty(image,"cipher:type");
684   (void) DeleteImageProperty(image,"cipher:mode");
685   (void) DeleteImageProperty(image,"cipher:nonce");
686   image->taint=MagickFalse;
687   /*
688     Free resources.
689   */
690   quantum_info=DestroyQuantumInfo(quantum_info);
691   aes_info=DestroyAESInfo(aes_info);
692   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
693   (void) ResetMagickMemory(output_block,0,sizeof(output_block));
694   return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
695 }
696 \f
697 /*
698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699 %                                                                             %
700 %                                                                             %
701 %                                                                             %
702 %     P a s s k e y E n c i p h e r I m a g e                                 %
703 %                                                                             %
704 %                                                                             %
705 %                                                                             %
706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 %
708 %  PasskeyEncipherImage() converts pixels to cipher-pixels.
709 %
710 %  The format of the PasskeyEncipherImage method is:
711 %
712 %      MagickBooleanType PasskeyEncipherImage(Image *image,
713 %        const StringInfo *passkey,ExceptionInfo *exception)
714 %      MagickBooleanType EncipherImage(Image *image,const char *passphrase,
715 %        ExceptionInfo *exception)
716 %
717 %  A description of each parameter follows:
718 %
719 %    o image: the image.
720 %
721 %    o passphrase: encipher pixels with this passphrase.
722 %
723 %    o passkey: decrypt cipher pixels with this passkey.
724 %
725 %    o exception: return any errors or warnings in this structure.
726 %
727 */
728
729 MagickExport MagickBooleanType EncipherImage(Image *image,
730   const char *passphrase,ExceptionInfo *exception)
731 {
732   MagickBooleanType
733     status;
734
735   StringInfo
736     *passkey;
737
738   if (passphrase == (const char *) NULL)
739     return(MagickTrue);
740   passkey=StringToStringInfo(passphrase);
741   if (passkey == (StringInfo *) NULL)
742     return(MagickFalse);
743   status=PasskeyEncipherImage(image,passkey,exception);
744   passkey=DestroyStringInfo(passkey);
745   return(status);
746 }
747
748 MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
749   const StringInfo *passkey,ExceptionInfo *exception)
750 {
751 #define EncipherImageTag  "Encipher/Image "
752
753   AESInfo
754     *aes_info;
755
756   CacheView
757     *image_view;
758
759   char
760     *signature;
761
762   const unsigned char
763     *digest;
764
765   IndexPacket
766     *indexes;
767
768   ssize_t
769     y;
770
771   MagickBooleanType
772     proceed;
773
774   QuantumInfo
775     *quantum_info;
776
777   QuantumType
778     quantum_type;
779
780   register unsigned char
781     *p;
782
783   SignatureInfo
784     *signature_info;
785
786   size_t
787     length;
788
789   StringInfo
790     *key,
791     *nonce;
792
793   unsigned char
794     input_block[AESBlocksize],
795     output_block[AESBlocksize],
796     *pixels;
797
798   /*
799     Generate encipher key and nonce.
800   */
801   assert(image != (Image *) NULL);
802   assert(image->signature == MagickSignature);
803   if (image->debug != MagickFalse)
804     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
805   assert(exception != (ExceptionInfo *) NULL);
806   assert(exception->signature == MagickSignature);
807   if (passkey == (const StringInfo *) NULL)
808     return(MagickTrue);
809   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
810     return(MagickFalse);
811   quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
812   if (quantum_info == (QuantumInfo *) NULL)
813     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
814       image->filename);
815   aes_info=AcquireAESInfo();
816   key=CloneStringInfo(passkey);
817   if (key == (StringInfo *) NULL)
818     {
819       aes_info=DestroyAESInfo(aes_info);
820       quantum_info=DestroyQuantumInfo(quantum_info);
821       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
822         image->filename);
823     }
824   nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
825   if (nonce == (StringInfo *) NULL)
826     {
827       key=DestroyStringInfo(key);
828       aes_info=DestroyAESInfo(aes_info);
829       quantum_info=DestroyQuantumInfo(quantum_info);
830       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
831         image->filename);
832     }
833   SetAESKey(aes_info,key);
834   key=DestroyStringInfo(key);
835   signature_info=AcquireSignatureInfo();
836   UpdateSignature(signature_info,nonce);
837   SetStringInfoLength(nonce,sizeof(quantum_info->extent));
838   SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
839   UpdateSignature(signature_info,nonce);
840   nonce=DestroyStringInfo(nonce);
841   FinalizeSignature(signature_info);
842   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
843   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
844   (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
845     GetSignatureDigestsize(signature_info))*sizeof(*input_block));
846   signature=StringInfoToHexString(GetSignatureDigest(signature_info));
847   (void) SetImageProperty(image,"cipher:type","AES");
848   (void) SetImageProperty(image,"cipher:mode","CFB");
849   (void) SetImageProperty(image,"cipher:nonce",signature);
850   signature=DestroyString(signature);
851   signature_info=DestroySignatureInfo(signature_info);
852   /*
853     Convert plain pixels to cipher pixels.
854   */
855   quantum_type=GetQuantumType(image,exception);
856   pixels=GetQuantumPixels(quantum_info);
857   image_view=AcquireCacheView(image);
858   for (y=0; y < (ssize_t) image->rows; y++)
859   {
860     register ssize_t
861       x;
862
863     register PixelPacket
864       *restrict q;
865
866     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
867     if (q == (PixelPacket *) NULL)
868       break;
869     indexes=GetCacheViewAuthenticIndexQueue(image_view);
870     length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
871       pixels,exception);
872     p=pixels;
873     for (x=0; x < (ssize_t) length; x++)
874     {
875       (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
876         sizeof(*output_block));
877       EncipherAESBlock(aes_info,output_block,output_block);
878       *p^=(*output_block);
879       (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
880         sizeof(*input_block));
881       input_block[AESBlocksize-1]=(*p++);
882     }
883     (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
884       pixels,exception);
885     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
886       break;
887     proceed=SetImageProgress(image,EncipherImageTag,(MagickOffsetType) y,
888       image->rows);
889     if (proceed == MagickFalse)
890       break;
891   }
892   image_view=DestroyCacheView(image_view);
893   image->taint=MagickFalse;
894   /*
895     Free resources.
896   */
897   quantum_info=DestroyQuantumInfo(quantum_info);
898   aes_info=DestroyAESInfo(aes_info);
899   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
900   (void) ResetMagickMemory(output_block,0,sizeof(output_block));
901   return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
902 }
903 \f
904 /*
905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
906 %                                                                             %
907 %                                                                             %
908 %                                                                             %
909 %   S e t A E S K e y                                                         %
910 %                                                                             %
911 %                                                                             %
912 %                                                                             %
913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
914 %
915 %  SetAESKey() sets the key for the AES cipher.  The key length is specified
916 %  in bits.  Valid values are 128, 192, or 256 requiring a key buffer length
917 %  in bytes of 16, 24, and 32 respectively.
918 %
919 %  The format of the SetAESKey method is:
920 %
921 %      SetAESKey(AESInfo *aes_info,const StringInfo *key)
922 %
923 %  A description of each parameter follows:
924 %
925 %    o aes_info: the cipher context.
926 %
927 %    o key: the key.
928 %
929 */
930
931 static inline void InverseAddRoundKey(const unsigned int *alpha,
932   unsigned int *beta)
933 {
934   register unsigned int
935     i,
936     j;
937
938   for (i=0; i < 4; i++)
939   {
940     beta[i]=0;
941     for (j=0; j < 4; j++)
942       beta[i]|=(ByteMultiply(0xe,(alpha[i] >> (8*j)) & 0xff) ^
943         ByteMultiply(0xb,(alpha[i] >> (8*((j+1) % 4))) & 0xff) ^
944         ByteMultiply(0xd,(alpha[i] >> (8*((j+2) % 4))) & 0xff) ^
945         ByteMultiply(0x9,(alpha[i] >> (8*((j+3) % 4))) & 0xff)) << (8*j);
946   }
947 }
948
949 static inline unsigned int XTime(unsigned char alpha)
950 {
951   unsigned char
952     beta;
953
954   beta=(unsigned char) ((alpha & 0x80) != 0 ? 0x1b : 0);
955   alpha<<=1;
956   alpha^=beta;
957   return(alpha);
958 }
959
960 static inline unsigned int RotateRight(const unsigned int x)
961 {
962   return((x >> 8) | ((x & 0xff) << 24));
963 }
964
965 static void SetAESKey(AESInfo *aes_info,const StringInfo *key)
966 {
967   ssize_t
968     bytes,
969     n;
970
971   register ssize_t
972     i;
973
974   unsigned char
975     *datum;
976
977   unsigned int
978     alpha,
979     beta;
980
981   /*
982     Determine the number of rounds based on the number of bits in key.
983   */
984   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
985   assert(aes_info != (AESInfo *) NULL);
986   assert(aes_info->signature == MagickSignature);
987   assert(key != (StringInfo *) NULL);
988   n=4;
989   aes_info->rounds=10;
990   if ((8*GetStringInfoLength(key)) >= 256)
991     {
992       n=8;
993       aes_info->rounds=14;
994     }
995   else
996     if ((8*GetStringInfoLength(key)) >= 192)
997       {
998         n=6;
999         aes_info->rounds=12;
1000       }
1001   /*
1002     Generate crypt key.
1003   */
1004   datum=GetStringInfoDatum(aes_info->key);
1005   (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1006   (void) CopyMagickMemory(datum,GetStringInfoDatum(key),MagickMin(
1007     GetStringInfoLength(key),GetStringInfoLength(aes_info->key)));
1008   for (i=0; i < n; i++)
1009     aes_info->encipher_key[i]=datum[4*i] | (datum[4*i+1] << 8) |
1010       (datum[4*i+2] << 16) | (datum[4*i+3] << 24);
1011   beta=1;
1012   bytes=(AESBlocksize/4)*(aes_info->rounds+1);
1013   for (i=n; i < bytes; i++)
1014   {
1015     alpha=aes_info->encipher_key[i-1];
1016     if ((i % n) == 0)
1017       {
1018         alpha=ByteSubTransform(RotateRight(alpha),SBox) ^ beta;
1019         beta=XTime((unsigned char) (beta & 0xff));
1020       }
1021     else
1022       if ((n > 6) && ((i % n) == 4))
1023         alpha=ByteSubTransform(alpha,SBox);
1024     aes_info->encipher_key[i]=aes_info->encipher_key[i-n] ^ alpha;
1025   }
1026   /*
1027     Generate deciper key (in reverse order).
1028   */
1029   for (i=0; i < 4; i++)
1030   {
1031     aes_info->decipher_key[i]=aes_info->encipher_key[i];
1032     aes_info->decipher_key[bytes-4+i]=aes_info->encipher_key[bytes-4+i];
1033   }
1034   for (i=4; i < (bytes-4); i+=4)
1035     InverseAddRoundKey(aes_info->encipher_key+i,aes_info->decipher_key+i);
1036   /*
1037     Reset registers.
1038   */
1039   datum=GetStringInfoDatum(aes_info->key);
1040   (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1041   alpha=0;
1042   beta=0;
1043 }
1044 #else
1045 \f
1046 /*
1047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048 %                                                                             %
1049 %                                                                             %
1050 %                                                                             %
1051 %     P a s s k e y D e c i p h e r I m a g e                                 %
1052 %                                                                             %
1053 %                                                                             %
1054 %                                                                             %
1055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1056 %
1057 %  PasskeyDecipherImage() converts cipher pixels to plain pixels.
1058 %
1059 %  The format of the PasskeyDecipherImage method is:
1060 %
1061 %      MagickBooleanType PasskeyDecipherImage(Image *image,
1062 %        const StringInfo *passkey,ExceptionInfo *exception)
1063 %      MagickBooleanType DecipherImage(Image *image,const char *passphrase,
1064 %        ExceptionInfo *exception)
1065 %
1066 %  A description of each parameter follows:
1067 %
1068 %    o image: the image.
1069 %
1070 %    o passphrase: decipher cipher pixels with this passphrase.
1071 %
1072 %    o passkey: decrypt cipher pixels with this passkey.
1073 %
1074 %    o exception: return any errors or warnings in this structure.
1075 %
1076 */
1077
1078 MagickExport MagickBooleanType DecipherImage(Image *image,
1079   const char *passphrase,ExceptionInfo *exception)
1080 {
1081   assert(image != (Image *) NULL);
1082   assert(image->signature == MagickSignature);
1083   if (image->debug != MagickFalse)
1084     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1085   assert(exception != (ExceptionInfo *) NULL);
1086   assert(exception->signature == MagickSignature);
1087   (void) passphrase;
1088   ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1089 }
1090
1091 MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
1092   const StringInfo *passkey,ExceptionInfo *exception)
1093 {
1094   assert(image != (Image *) NULL);
1095   assert(image->signature == MagickSignature);
1096   if (image->debug != MagickFalse)
1097     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1098   assert(exception != (ExceptionInfo *) NULL);
1099   assert(exception->signature == MagickSignature);
1100   (void) passkey;
1101   ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1102 }
1103 \f
1104 /*
1105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106 %                                                                             %
1107 %                                                                             %
1108 %                                                                             %
1109 %     P a s s k e y E n c i p h e r I m a g e                                 %
1110 %                                                                             %
1111 %                                                                             %
1112 %                                                                             %
1113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 %
1115 %  PasskeyEncipherImage() converts pixels to cipher-pixels.
1116 %
1117 %  The format of the PasskeyEncipherImage method is:
1118 %
1119 %      MagickBooleanType PasskeyEncipherImage(Image *image,
1120 %        const StringInfo *passkey,ExceptionInfo *exception)
1121 %      MagickBooleanType EncipherImage(Image *image,const char *passphrase,
1122 %        ExceptionInfo *exception)
1123 %
1124 %  A description of each parameter follows:
1125 %
1126 %    o passphrase: decipher cipher pixels with this passphrase.
1127 %
1128 %    o passkey: decrypt cipher pixels with this passkey.
1129 %
1130 %    o exception: return any errors or warnings in this structure.
1131 %
1132 */
1133
1134 MagickExport MagickBooleanType EncipherImage(Image *image,
1135   const char *passphrase,ExceptionInfo *exception)
1136 {
1137   assert(image != (Image *) NULL);
1138   assert(image->signature == MagickSignature);
1139   if (image->debug != MagickFalse)
1140     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1141   assert(exception != (ExceptionInfo *) NULL);
1142   assert(exception->signature == MagickSignature);
1143   (void) passphrase;
1144   ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1145 }
1146
1147 MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
1148   const StringInfo *passkey,ExceptionInfo *exception)
1149 {
1150   assert(image != (Image *) NULL);
1151   assert(image->signature == MagickSignature);
1152   if (image->debug != MagickFalse)
1153     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1154   assert(exception != (ExceptionInfo *) NULL);
1155   assert(exception->signature == MagickSignature);
1156   (void) passkey;
1157   ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1158 }
1159 #endif