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