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