root/ImageMagick/trunk/magick/cipher.c

Revision 1, 40.0 KB (checked in by cristy, 3 months ago)


Line 
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-2009 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 "magick/studio.h"
42#include "magick/cache.h"
43#include "magick/cipher.h"
44#include "magick/exception.h"
45#include "magick/exception-private.h"
46#include "magick/hashmap.h"
47#include "magick/image.h"
48#include "magick/image-private.h"
49#include "magick/list.h"
50#include "magick/memory_.h"
51#include "magick/monitor.h"
52#include "magick/monitor-private.h"
53#include "magick/property.h"
54#include "magick/quantum-private.h"
55#include "magick/registry.h"
56#include "magick/semaphore.h"
57#include "magick/signature-private.h"
58#include "magick/splay-tree.h"
59#include "magick/statistic.h"
60#include "magick/string_.h"
61
62#if defined(MAGICKCORE_CIPHER_SUPPORT)
63/*
64  Define declarations.
65*/
66#define AESBlocksize 16
67
68/*
69  Typedef declarations.
70*/
71typedef struct _AESInfo
72{
73  StringInfo
74    *key;
75
76  unsigned int
77    blocksize,
78    *encipher_key,
79    *decipher_key;
80
81  long
82    rounds,
83    timestamp;
84
85  unsigned long
86    signature;
87} AESInfo;
88
89/*
90  Global declarations.
91*/
92static unsigned char
93  InverseLog[256] =
94  {
95      1,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,
96     19,  53,  95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,
97     30,  34, 102, 170, 229,  52,  92, 228,  55,  89, 235,  38, 106, 190,
98    217, 112, 144, 171, 230,  49,  83, 245,   4,  12,  20,  60,  68, 204,
99     79, 209, 104, 184, 211, 110, 178, 205,  76, 212, 103, 169, 224,  59,
100     77, 215,  98, 166, 241,   8,  24,  40, 120, 136, 131, 158, 185, 208,
101    107, 189, 220, 127, 129, 152, 179, 206,  73, 219, 118, 154, 181, 196,
102     87, 249,  16,  48,  80, 240,  11,  29,  39, 105, 187, 214,  97, 163,
103    254,  25,  43, 125, 135, 146, 173, 236,  47, 113, 147, 174, 233,  32,
104     96, 160, 251,  22,  58,  78, 210, 109, 183, 194,  93, 231,  50,  86,
105    250,  21,  63,  65, 195,  94, 226,  61,  71, 201,  64, 192,  91, 237,
106     44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239,  42, 126,
107    130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193,  88, 232,  35,
108    101, 175, 234,  37, 111, 177, 200,  67, 197,  84, 252,  31,  33,  99,
109    165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,  69, 207,
110     74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,
111     18,  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,
112     13,  23,  57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180,
113    199,  82, 246,   1
114  },
115  Log[256] =
116  {
117      0,   0,  25,   1,  50,   2,  26, 198,  75, 199,  27, 104,  51, 238,
118    223,   3, 100,   4, 224,  14,  52, 141, 129, 239,  76, 113,   8, 200,
119    248, 105,  28, 193, 125, 194,  29, 181, 249, 185,  39, 106,  77, 228,
120    166, 114, 154, 201,   9, 120, 101,  47, 138,   5,  33,  15, 225,  36,
121     18, 240, 130,  69,  53, 147, 218, 142, 150, 143, 219, 189,  54, 208,
122    206, 148,  19,  92, 210, 241,  64,  70, 131,  56, 102, 221, 253,  48,
123    191,   6, 139,  98, 179,  37, 226, 152,  34, 136, 145,  16, 126, 110,
124     72, 195, 163, 182,  30,  66,  58, 107,  40,  84, 250, 133,  61, 186,
125     43, 121,  10,  21, 155, 159,  94, 202,  78, 212, 172, 229, 243, 115,
126    167,  87, 175,  88, 168,  80, 244, 234, 214, 116,  79, 174, 233, 213,
127    231, 230, 173, 232,  44, 215, 117, 122, 235,  22,  11, 245,  89, 203,
128     95, 176, 156, 169,  81, 160, 127,  12, 246, 111,  23, 196,  73, 236,
129    216,  67,  31,  45, 164, 118, 123, 183, 204, 187,  62,  90, 251,  96,
130    177, 134,  59,  82, 161, 108, 170,  85,  41, 157, 151, 178, 135, 144,
131     97, 190, 220, 252, 188, 149, 207, 205,  55,  63,  91, 209,  83,  57,
132    132, 60,   65, 162, 109,  71,  20,  42, 158,  93,  86, 242, 211, 171,
133     68,  17, 146, 217,  35,  32,  46, 137, 180, 124, 184,  38, 119, 153,
134    227, 165, 103,  74, 237, 222, 197,  49, 254,  24,  13,  99, 140, 128,
135    192, 247, 112,   7,
136  },
137  SBox[256] =
138  {
139     99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215,
140    171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175,
141    156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165,
142    229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,
143      7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110,
144     90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237,
145     32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239,
146    170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
147     81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255,
148    243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61,
149    100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238,
150    184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92,
151    194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
152     78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46,
153     28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62,
154    181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
155    225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,
156     40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15,
157    176,  84, 187, 22
158  };
159
160/*
161  Forward declarations.
162*/
163static AESInfo
164  *DestroyAESInfo(AESInfo *);
165
166static void
167  EncipherAESBlock(AESInfo *,const unsigned char *,unsigned char *),
168  SetAESKey(AESInfo *,const StringInfo *);
169
170/*
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%                                                                             %
173%                                                                             %
174%                                                                             %
175%   A c q u i r e A E S I n f o                                               %
176%                                                                             %
177%                                                                             %
178%                                                                             %
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180%
181%  AcquireAESInfo() allocate the AESInfo structure.
182%
183%  The format of the AcquireAESInfo method is:
184%
185%      AESInfo *AcquireAESInfo(void)
186%
187*/
188static AESInfo *AcquireAESInfo(void)
189{
190  AESInfo
191    *aes_info;
192
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=(long) time(0);
208  aes_info->signature=MagickSignature;
209  return(aes_info);
210}
211
212/*
213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214%                                                                             %
215%                                                                             %
216%                                                                             %
217%   D e s t r o y A E S I n f o                                               %
218%                                                                             %
219%                                                                             %
220%                                                                             %
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222%
223%  DestroyAESInfo() zeros memory associated with the AESInfo structure.
224%
225%  The format of the DestroyAESInfo method is:
226%
227%      AESInfo *DestroyAESInfo(AESInfo *aes_info)
228%
229%  A description of each parameter follows:
230%
231%    o aes_info: the cipher context.
232%
233*/
234static AESInfo *DestroyAESInfo(AESInfo *aes_info)
235{
236  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
237  assert(aes_info != (AESInfo *) NULL);
238  assert(aes_info->signature == MagickSignature);
239  if (aes_info->decipher_key != (unsigned int *) NULL)
240    aes_info->decipher_key=(unsigned int *) RelinquishMagickMemory(
241      aes_info->decipher_key);
242  if (aes_info->encipher_key != (unsigned int *) NULL)
243    aes_info->encipher_key=(unsigned int *) RelinquishMagickMemory(
244      aes_info->encipher_key);
245  if (aes_info->key != (StringInfo *) NULL)
246    aes_info->key=DestroyStringInfo(aes_info->key);
247  aes_info->signature=(~MagickSignature);
248  aes_info=(AESInfo *) RelinquishMagickMemory(aes_info);
249  return(aes_info);
250}
251
252/*
253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254%                                                                             %
255%                                                                             %
256%                                                                             %
257%   E n c i p h e r A E S B l o c k                                           %
258%                                                                             %
259%                                                                             %
260%                                                                             %
261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262%
263%  EncipherAESBlock() enciphers a single block of plaintext to produce a block
264%  of ciphertext.
265%
266%  The format of the EncipherAESBlock method is:
267%
268%      void EncipherAES(AESInfo *aes_info,const unsigned char *plaintext,
269%        unsigned char *ciphertext)
270%
271%  A description of each parameter follows:
272%
273%    o aes_info: the cipher context.
274%
275%    o plaintext: the plain text.
276%
277%    o ciphertext: the cipher text.
278%
279*/
280
281static inline void AddRoundKey(const unsigned int *ciphertext,
282  const unsigned int *key,unsigned int *plaintext)
283{
284  register long
285    i;
286
287  /*
288    Xor corresponding text input and round key input bytes.
289  */
290  for (i=0; i < 4; i++)
291    plaintext[i]=key[i] ^ ciphertext[i];
292}
293
294static inline unsigned char ByteMultiply(const unsigned char alpha,
295  const unsigned char beta)
296{
297  /*
298    Byte multiply two elements of GF(2^m) (mix columns and inverse mix columns).
299  */
300  if ((alpha == 0) || (beta == 0))
301    return(0);
302  return(InverseLog[(Log[alpha]+Log[beta]) % 0xff]);
303}
304
305static inline unsigned int ByteSubTransform(unsigned int x,
306  unsigned char *s_box)
307{
308  unsigned int
309    key;
310
311  /*
312    Non-linear layer resists differential and linear cryptoanalysis attacks.
313  */
314  key=(s_box[x & 0xff]) | (s_box[(x >> 8) & 0xff] << 8) |
315    (s_box[(x >> 16) & 0xff] << 16) | (s_box[(x >> 24) & 0xff] << 24);
316  return(key);
317}
318
319static void FinalizeRoundKey(const unsigned int *ciphertext,
320  const unsigned int *key,unsigned char *plaintext)
321{
322  register unsigned char
323    *p;
324
325  register unsigned int
326    i,
327    j;
328
329  unsigned int
330    value;
331
332  /*
333    The round key is XORed with the result of the mix-column transformation.
334  */
335  p=plaintext;
336  for (i=0; i < 4; i++)
337  {
338    value=ciphertext[i] ^ key[i];
339    for (j=0; j < 4; j++)
340      *p++=(value >> (8*j)) & 0xff;
341  }
342  /*
343    Reset registers.
344  */
345  value=0;
346}
347
348static void InitializeRoundKey(const unsigned char *ciphertext,
349  const unsigned int *key,unsigned int *plaintext)
350{
351  register const unsigned char
352    *p;
353
354  register unsigned int
355    i,
356    j;
357
358  unsigned int
359    value;
360
361  p=ciphertext;
362  for (i=0; i < 4; i++)
363  {
364    value=0;
365    for (j=0; j < 4; j++)
366      value|=(*p++ << (8*j));
367    plaintext[i]=key[i] ^ value;
368  }
369  /*
370    Reset registers.
371  */
372  value=0;
373}
374
375static inline unsigned int RotateLeft(const unsigned int x)
376{
377  return(((x << 8) | ((x >> 24) & 0xff)));
378}
379
380static void EncipherAESBlock(AESInfo *aes_info,const unsigned char *plaintext,
381  unsigned char *ciphertext)
382{
383  register long
384    i,
385    j;
386
387  static int
388    map[4][4] =
389    {
390      { 0, 1, 2, 3 },
391      { 1, 2, 3, 0 },
392      { 2, 3, 0, 1 },
393      { 3, 0, 1, 2 }
394    };
395
396  static unsigned int
397    D[] =
398    {
399      0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U, 0x0df2f2ffU,
400      0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U, 0x50303060U, 0x03010102U,
401      0xa96767ceU, 0x7d2b2b56U, 0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU,
402      0x9a7676ecU, 0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU,
403      0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU, 0xecadad41U,
404      0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U, 0xbf9c9c23U, 0xf7a4a453U,
405      0x967272e4U, 0x5bc0c09bU, 0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU,
406      0x6a26264cU, 0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U,
407      0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U, 0x937171e2U,
408      0x73d8d8abU, 0x53313162U, 0x3f15152aU, 0x0c040408U, 0x52c7c795U,
409      0x65232346U, 0x5ec3c39dU, 0x28181830U, 0xa1969637U, 0x0f05050aU,
410      0xb59a9a2fU, 0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU,
411      0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU, 0x1b090912U,
412      0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U, 0x2d1b1b36U, 0xb26e6edcU,
413      0xee5a5ab4U, 0xfba0a05bU, 0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U,
414      0xceb3b37dU, 0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U,
415      0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U, 0x60202040U,
416      0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U, 0xbe6a6ad4U, 0x46cbcb8dU,
417      0xd9bebe67U, 0x4b393972U, 0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U,
418      0x4acfcf85U, 0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU,
419      0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U, 0xcf45458aU,
420      0x10f9f9e9U, 0x06020204U, 0x817f7ffeU, 0xf05050a0U, 0x443c3c78U,
421      0xba9f9f25U, 0xe3a8a84bU, 0xf35151a2U, 0xfea3a35dU, 0xc0404080U,
422      0x8a8f8f05U, 0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U,
423      0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U, 0x30101020U,
424      0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU, 0x4ccdcd81U, 0x140c0c18U,
425      0x35131326U, 0x2fececc3U, 0xe15f5fbeU, 0xa2979735U, 0xcc444488U,
426      0x3917172eU, 0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU,
427      0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U, 0xa06060c0U,
428      0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U, 0x66222244U, 0x7e2a2a54U,
429      0xab90903bU, 0x8388880bU, 0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU,
430      0x3c141428U, 0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU,
431      0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U, 0xdb494992U,
432      0x0a06060cU, 0x6c242448U, 0xe45c5cb8U, 0x5dc2c29fU, 0x6ed3d3bdU,
433      0xefacac43U, 0xa66262c4U, 0xa8919139U, 0xa4959531U, 0x37e4e4d3U,
434      0x8b7979f2U, 0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU,
435      0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U, 0xb46c6cd8U,
436      0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU, 0xaf6565caU, 0x8e7a7af4U,
437      0xe9aeae47U, 0x18080810U, 0xd5baba6fU, 0x887878f0U, 0x6f25254aU,
438      0x722e2e5cU, 0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U,
439      0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU, 0xdd4b4b96U,
440      0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU, 0x907070e0U, 0x423e3e7cU,
441      0xc4b5b571U, 0xaa6666ccU, 0xd8484890U, 0x05030306U, 0x01f6f6f7U,
442      0x120e0e1cU, 0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U,
443      0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U, 0x38e1e1d9U,
444      0x13f8f8ebU, 0xb398982bU, 0x33111122U, 0xbb6969d2U, 0x70d9d9a9U,
445      0x898e8e07U, 0xa7949433U, 0xb69b9b2dU, 0x221e1e3cU, 0x92878715U,
446      0x20e9e9c9U, 0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U,
447      0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU, 0xdabfbf65U,
448      0x31e6e6d7U, 0xc6424284U, 0xb86868d0U, 0xc3414182U, 0xb0999929U,
449      0x772d2d5aU, 0x110f0f1eU, 0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU,
450      0x3a16162cU
451    };
452
453  unsigned int
454    alpha,
455    key[4],
456    text[4];
457
458  /*
459    Encipher one block.
460  */
461  (void) memset(text,0,sizeof(text));
462  InitializeRoundKey(plaintext,aes_info->encipher_key,text);
463  for (i=1; i < aes_info->rounds; i++)
464  {
465    /*
466      Linear mixing step: cause diffusion of the bits over multiple rounds.
467    */
468    for (j=0; j < 4; j++)
469      key[j]=D[text[j] & 0xff] ^
470        RotateLeft(D[(text[map[1][j]] >> 8) & 0xff] ^
471        RotateLeft(D[(text[map[2][j]] >> 16) & 0xff] ^
472        RotateLeft(D[(text[map[3][j]] >> 24) & 0xff])));
473    AddRoundKey(key,aes_info->encipher_key+4*i,text);
474  }
475  for (i=0; i < 4; i++)
476  {
477    alpha=(text[i] & 0x000000ff) | ((text[map[1][i]]) & 0x0000ff00) |
478      ((text[map[2][i]]) & 0x00ff0000) | ((text[map[3][i]]) & 0xff000000);
479    key[i]=ByteSubTransform(alpha,SBox);
480  }
481  FinalizeRoundKey(key,aes_info->encipher_key+4*aes_info->rounds,ciphertext);
482  /*
483    Reset registers.
484  */
485  alpha=0;
486  (void) ResetMagickMemory(key,0,sizeof(key));
487  (void) ResetMagickMemory(text,0,sizeof(text));
488}
489
490/*
491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492%                                                                             %
493%                                                                             %
494%                                                                             %
495%     P a s s k e y D e c i p h e r I m a g e                                 %
496%                                                                             %
497%                                                                             %
498%                                                                             %
499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500%
501%  PasskeyDecipherImage() converts cipher pixels to plain pixels.
502%
503%  The format of the PasskeyDecipherImage method is:
504%
505%      MagickBooleanType PasskeyDecipherImage(Image *image,
506%        const StringInfo *passkey,ExceptionInfo *exception)
507%      MagickBooleanType DecipherImage(Image *image,const char *passphrase,
508%        ExceptionInfo *exception)
509%
510%  A description of each parameter follows:
511%
512%    o image: the image.
513%
514%    o passphrase: decipher cipher pixels with this passphrase.
515%
516%    o passkey: decrypt cipher pixels with this passkey.
517%
518%    o exception: return any errors or warnings in this structure.
519%
520*/
521
522static inline size_t MagickMin(const size_t x,const size_t y)
523{
524  if (x < y)
525    return(x);
526  return(y);
527}
528
529MagickExport MagickBooleanType DecipherImage(Image *image,
530  const char *passphrase,ExceptionInfo *exception)
531{
532  MagickBooleanType
533    status;
534
535  StringInfo
536    *passkey;
537
538  if (passphrase == (const char *) NULL)
539    return(MagickTrue);
540  passkey=StringToStringInfo(passphrase);
541  if (passkey == (StringInfo *) NULL)
542    return(MagickFalse);
543  status=PasskeyDecipherImage(image,passkey,exception);
544  passkey=DestroyStringInfo(passkey);
545  return(status);
546}
547
548MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
549  const StringInfo *passkey,ExceptionInfo *exception)
550{
551#define DecipherImageTag  "Decipher/Image "
552
553  AESInfo
554    *aes_info;
555
556  const unsigned char
557    *digest;
558
559  IndexPacket
560    *indexes;
561
562  long
563    y;
564
565  MagickBooleanType
566    proceed;
567
568  QuantumInfo
569    *quantum_info;
570
571  QuantumType
572    quantum_type;
573
574  SignatureInfo
575    *signature_info;
576
577  register unsigned char
578    *p;
579
580  size_t
581    length;
582
583  StringInfo
584    *key,
585    *nonce;
586
587  unsigned char
588    input_block[AESBlocksize],
589    output_block[AESBlocksize],
590    *pixels;
591
592  CacheView
593    *image_view;
594
595  /*
596    Generate decipher key and nonce.
597  */
598  assert(image != (Image *) NULL);
599  assert(image->signature == MagickSignature);
600  if (image->debug != MagickFalse)
601    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
602  assert(exception != (ExceptionInfo *) NULL);
603  assert(exception->signature == MagickSignature);
604  if (passkey == (const StringInfo *) NULL)
605    return(MagickTrue);
606  quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
607  if (quantum_info == (QuantumInfo *) NULL)
608    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
609      image->filename);
610  aes_info=AcquireAESInfo();
611  key=CloneStringInfo(passkey);
612  if (key == (StringInfo *) NULL)
613    {
614      aes_info=DestroyAESInfo(aes_info);
615      quantum_info=DestroyQuantumInfo(quantum_info);
616      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
617        image->filename);
618    }
619  nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
620  if (nonce == (StringInfo *) NULL)
621    {
622      key=DestroyStringInfo(key);
623      aes_info=DestroyAESInfo(aes_info);
624      quantum_info=DestroyQuantumInfo(quantum_info);
625      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
626        image->filename);
627    }
628  SetAESKey(aes_info,key);
629  key=DestroyStringInfo(key);
630  signature_info=AcquireSignatureInfo();
631  UpdateSignature(signature_info,nonce);
632  SetStringInfoLength(nonce,sizeof(quantum_info->extent));
633  SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
634  UpdateSignature(signature_info,nonce);
635  FinalizeSignature(signature_info);
636  (void) ResetMagickMemory(input_block,0,sizeof(input_block));
637  digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
638  (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
639    GetSignatureDigestsize(signature_info))*sizeof(*input_block));
640  nonce=DestroyStringInfo(nonce);
641  signature_info=DestroySignatureInfo(signature_info);
642  /*
643    Convert cipher pixels to plain pixels.
644  */
645  quantum_type=GetQuantumType(image,exception);
646  pixels=GetQuantumPixels(quantum_info);
647  image_view=AcquireCacheView(image);
648  for (y=0; y < (long) image->rows; y++)
649  {
650    register long
651      x;
652
653    register PixelPacket
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 < (long) length; x++)
664    {
665      (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
666        sizeof(*output_block));
667      EncipherAESBlock(aes_info,output_block,output_block);
668      (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
669        sizeof(*input_block));
670      input_block[AESBlocksize-1]=(*p);
671      *p++^=(*output_block);
672    }
673    (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
674      pixels,exception);
675    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
676      break;
677    proceed=SetImageProgress(image,DecipherImageTag,y,image->rows);
678    if (proceed == MagickFalse)
679      break;
680  }
681  image_view=DestroyCacheView(image_view);
682  (void) DeleteImageProperty(image,"cipher:type");
683  (void) DeleteImageProperty(image,"cipher:mode");
684  (void) DeleteImageProperty(image,"cipher:nonce");
685  image->taint=MagickFalse;
686  /*
687    Free resources.
688  */
689  quantum_info=DestroyQuantumInfo(quantum_info);
690  aes_info=DestroyAESInfo(aes_info);
691  (void) ResetMagickMemory(input_block,0,sizeof(input_block));
692  (void) ResetMagickMemory(output_block,0,sizeof(output_block));
693  return(y == (long) image->rows ? MagickTrue : MagickFalse);
694}
695
696/*
697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698%                                                                             %
699%                                                                             %
700%                                                                             %
701%     P a s s k e y E n c i p h e r I m a g e                                 %
702%                                                                             %
703%                                                                             %
704%                                                                             %
705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706%
707%  PasskeyEncipherImage() converts pixels to cipher-pixels.
708%
709%  The format of the PasskeyEncipherImage method is:
710%
711%      MagickBooleanType PasskeyEncipherImage(Image *image,
712%        const StringInfo *passkey,ExceptionInfo *exception)
713%      MagickBooleanType EncipherImage(Image *image,const char *passphrase,
714%        ExceptionInfo *exception)
715%
716%  A description of each parameter follows:
717%
718%    o image: the image.
719%
720%    o passphrase: encipher pixels with this passphrase.
721%
722%    o passkey: decrypt cipher pixels with this passkey.
723%
724%    o exception: return any errors or warnings in this structure.
725%
726*/
727
728MagickExport MagickBooleanType EncipherImage(Image *image,
729  const char *passphrase,ExceptionInfo *exception)
730{
731  MagickBooleanType
732    status;
733
734  StringInfo
735    *passkey;
736
737  if (passphrase == (const char *) NULL)
738    return(MagickTrue);
739  passkey=StringToStringInfo(passphrase);
740  if (passkey == (StringInfo *) NULL)
741    return(MagickFalse);
742  status=PasskeyEncipherImage(image,passkey,exception);
743  passkey=DestroyStringInfo(passkey);
744  return(status);
745}
746
747MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
748  const StringInfo *passkey,ExceptionInfo *exception)
749{
750#define EncipherImageTag  "Encipher/Image "
751
752  AESInfo
753    *aes_info;
754
755  char
756    *signature;
757
758  const unsigned char
759    *digest;
760
761  IndexPacket
762    *indexes;
763
764  long
765    y;
766
767  MagickBooleanType
768    proceed;
769
770  QuantumInfo
771    *quantum_info;
772
773  QuantumType
774    quantum_type;
775
776  register unsigned char
777    *p;
778
779  SignatureInfo
780    *signature_info;
781
782  size_t
783    length;
784
785  StringInfo
786    *key,
787    *nonce;
788
789  unsigned char
790    input_block[AESBlocksize],
791    output_block[AESBlocksize],
792    *pixels;
793
794  CacheView
795    *image_view;
796
797  /*
798    Generate encipher key and nonce.
799  */
800  assert(image != (Image *) NULL);
801  assert(image->signature == MagickSignature);
802  if (image->debug != MagickFalse)
803    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
804  assert(exception != (ExceptionInfo *) NULL);
805  assert(exception->signature == MagickSignature);
806  if (passkey == (const StringInfo *) NULL)
807    return(MagickTrue);
808  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
809    return(MagickFalse);
810  quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
811  if (quantum_info == (QuantumInfo *) NULL)
812    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
813      image->filename);
814  aes_info=AcquireAESInfo();
815  key=CloneStringInfo(passkey);
816  if (key == (StringInfo *) NULL)
817    {
818      aes_info=DestroyAESInfo(aes_info);
819      quantum_info=DestroyQuantumInfo(quantum_info);
820      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
821        image->filename);
822    }
823  nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
824  if (nonce == (StringInfo *) NULL)
825    {
826      key=DestroyStringInfo(key);
827      aes_info=DestroyAESInfo(aes_info);
828      quantum_info=DestroyQuantumInfo(quantum_info);
829      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
830        image->filename);
831    }
832  SetAESKey(aes_info,key);
833  key=DestroyStringInfo(key);
834  signature_info=AcquireSignatureInfo();
835  UpdateSignature(signature_info,nonce);
836  SetStringInfoLength(nonce,sizeof(quantum_info->extent));
837  SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
838  UpdateSignature(signature_info,nonce);
839  nonce=DestroyStringInfo(nonce);
840  FinalizeSignature(signature_info);
841  (void) ResetMagickMemory(input_block,0,sizeof(input_block));
842  digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
843  (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
844    GetSignatureDigestsize(signature_info))*sizeof(*input_block));
845  signature=StringInfoToHexString(GetSignatureDigest(signature_info));
846  (void) SetImageProperty(image,"cipher:type","AES");
847  (void) SetImageProperty(image,"cipher:mode","CFB");
848  (void) SetImageProperty(image,"cipher:nonce",signature);
849  signature=DestroyString(signature);
850  signature_info=DestroySignatureInfo(signature_info);
851  /*
852    Convert plain pixels to cipher pixels.
853  */
854  quantum_type=GetQuantumType(image,exception);
855  pixels=GetQuantumPixels(quantum_info);
856  image_view=AcquireCacheView(image);
857  for (y=0; y < (long) image->rows; y++)
858  {
859    register long
860      x;
861
862    register PixelPacket
863      *__restrict q;
864
865    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
866    if (q == (PixelPacket *) NULL)
867      break;
868    indexes=GetCacheViewAuthenticIndexQueue(image_view);
869    length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
870      pixels,exception);
871    p=pixels;
872    for (x=0; x < (long) length; x++)
873    {
874      (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
875        sizeof(*output_block));
876      EncipherAESBlock(aes_info,output_block,output_block);
877      *p^=(*output_block);
878      (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
879        sizeof(*input_block));
880      input_block[AESBlocksize-1]=(*p++);
881    }
882    (void) ImportQuantumPixels(image,image_view,quantum_info,quantum_type,
883      pixels,exception);
884    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
885      break;
886    proceed=SetImageProgress(image,EncipherImageTag,y,image->rows);
887    if (proceed == MagickFalse)
888      break;
889  }
890  image_view=DestroyCacheView(image_view);
891  image->taint=MagickFalse;
892  /*
893    Free resources.
894  */
895  quantum_info=DestroyQuantumInfo(quantum_info);
896  aes_info=DestroyAESInfo(aes_info);
897  (void) ResetMagickMemory(input_block,0,sizeof(input_block));
898  (void) ResetMagickMemory(output_block,0,sizeof(output_block));
899  return(y == (long) image->rows ? MagickTrue : MagickFalse);
900}
901
902/*
903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904%                                                                             %
905%                                                                             %
906%                                                                             %
907%   S e t A E S K e y                                                         %
908%                                                                             %
909%                                                                             %
910%                                                                             %
911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912%
913%  SetAESKey() sets the key for the AES cipher.  The key length is specified
914%  in bits.  Valid values are 128, 192, or 256 requiring a key buffer length
915%  in bytes of 16, 24, and 32 respectively.
916%
917%  The format of the SetAESKey method is:
918%
919%      SetAESKey(AESInfo *aes_info,const StringInfo *key)
920%
921%  A description of each parameter follows:
922%
923%    o aes_info: the cipher context.
924%
925%    o key: the key.
926%
927*/
928
929static inline void InverseAddRoundKey(const unsigned int *alpha,
930  unsigned int *beta)
931{
932  register unsigned int
933    i,
934    j;
935
936  for (i=0; i < 4; i++)
937  {
938    beta[i]=0;
939    for (j=0; j < 4; j++)
940      beta[i]|=(ByteMultiply(0xe,(alpha[i] >> (8*j)) & 0xff) ^
941        ByteMultiply(0xb,(alpha[i] >> (8*((j+1) % 4))) & 0xff) ^
942        ByteMultiply(0xd,(alpha[i] >> (8*((j+2) % 4))) & 0xff) ^
943        ByteMultiply(0x9,(alpha[i] >> (8*((j+3) % 4))) & 0xff)) << (8*j);
944  }
945}
946
947static inline unsigned int XTime(unsigned char alpha)
948{
949  unsigned char
950    beta;
951
952  beta=(unsigned char) ((alpha & 0x80) != 0 ? 0x1b : 0);
953  alpha<<=1;
954  alpha^=beta;
955  return(alpha);
956}
957
958static inline unsigned int RotateRight(const unsigned int x)
959{
960  return((x >> 8) | ((x & 0xff) << 24));
961}
962
963static void SetAESKey(AESInfo *aes_info,const StringInfo *key)
964{
965  long
966    bytes,
967    n;
968
969  register long
970    i;
971
972  unsigned char
973    *datum;
974
975  unsigned int
976    alpha,
977    beta;
978
979  /*
980    Determine the number of rounds based on the number of bits in key.
981  */
982  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
983  assert(aes_info != (AESInfo *) NULL);
984  assert(aes_info->signature == MagickSignature);
985  assert(key != (StringInfo *) NULL);
986  n=4;
987  aes_info->rounds=10;
988  if ((8*GetStringInfoLength(key)) >= 256)
989    {
990      n=8;
991      aes_info->rounds=14;
992    }
993  else
994    if ((8*GetStringInfoLength(key)) >= 192)
995      {
996        n=6;
997        aes_info->rounds=12;
998      }
999  /*
1000    Generate crypt key.
1001  */
1002  datum=GetStringInfoDatum(aes_info->key);
1003  (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1004  (void) CopyMagickMemory(datum,GetStringInfoDatum(key),MagickMin(
1005    GetStringInfoLength(key),GetStringInfoLength(aes_info->key)));
1006  for (i=0; i < n; i++)
1007    aes_info->encipher_key[i]=datum[4*i] | (datum[4*i+1] << 8) |
1008      (datum[4*i+2] << 16) | (datum[4*i+3] << 24);
1009  beta=1;
1010  bytes=(AESBlocksize/4)*(aes_info->rounds+1);
1011  for (i=n; i < bytes; i++)
1012  {
1013    alpha=aes_info->encipher_key[i-1];
1014    if ((i % n) == 0)
1015      {
1016        alpha=ByteSubTransform(RotateRight(alpha),SBox) ^ beta;
1017        beta=XTime((unsigned char) (beta & 0xff));
1018      }
1019    else
1020      if ((n > 6) && ((i % n) == 4))
1021        alpha=ByteSubTransform(alpha,SBox);
1022    aes_info->encipher_key[i]=aes_info->encipher_key[i-n] ^ alpha;
1023  }
1024  /*
1025    Generate deciper key (in reverse order).
1026  */
1027  for (i=0; i < 4; i++)
1028  {
1029    aes_info->decipher_key[i]=aes_info->encipher_key[i];
1030    aes_info->decipher_key[bytes-4+i]=aes_info->encipher_key[bytes-4+i];
1031  }
1032  for (i=4; i < (bytes-4); i+=4)
1033    InverseAddRoundKey(aes_info->encipher_key+i,aes_info->decipher_key+i);
1034  /*
1035    Reset registers.
1036  */
1037  datum=GetStringInfoDatum(aes_info->key);
1038  (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
1039  alpha=0;
1040  beta=0;
1041}
1042#else
1043
1044/*
1045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046%                                                                             %
1047%                                                                             %
1048%                                                                             %
1049%     P a s s k e y D e c i p h e r I m a g e                                 %
1050%                                                                             %
1051%                                                                             %
1052%                                                                             %
1053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054%
1055%  PasskeyDecipherImage() converts cipher pixels to plain pixels.
1056%
1057%  The format of the PasskeyDecipherImage method is:
1058%
1059%      MagickBooleanType PasskeyDecipherImage(Image *image,
1060%        const StringInfo *passkey,ExceptionInfo *exception)
1061%      MagickBooleanType DecipherImage(Image *image,const char *passphrase,
1062%        ExceptionInfo *exception)
1063%
1064%  A description of each parameter follows:
1065%
1066%    o image: the image.
1067%
1068%    o passphrase: decipher cipher pixels with this passphrase.
1069%
1070%    o passkey: decrypt cipher pixels with this passkey.
1071%
1072%    o exception: return any errors or warnings in this structure.
1073%
1074*/
1075
1076MagickExport MagickBooleanType DecipherImage(Image *image,
1077  const char *passphrase,ExceptionInfo *exception)
1078{
1079  assert(image != (Image *) NULL);
1080  assert(image->signature == MagickSignature);
1081  if (image->debug != MagickFalse)
1082    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1083  assert(exception != (ExceptionInfo *) NULL);
1084  assert(exception->signature == MagickSignature);
1085  (void) passphrase;
1086  ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1087}
1088
1089MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
1090  const StringInfo *passkey,ExceptionInfo *exception)
1091{
1092  assert(image != (Image *) NULL);
1093  assert(image->signature == MagickSignature);
1094  if (image->debug != MagickFalse)
1095    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1096  assert(exception != (ExceptionInfo *) NULL);
1097  assert(exception->signature == MagickSignature);
1098  (void) passkey;
1099  ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1100}
1101
1102/*
1103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104%                                                                             %
1105%                                                                             %
1106%                                                                             %
1107%     P a s s k e y E n c i p h e r I m a g e                                 %
1108%                                                                             %
1109%                                                                             %
1110%                                                                             %
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112%
1113%  PasskeyEncipherImage() converts pixels to cipher-pixels.
1114%
1115%  The format of the PasskeyEncipherImage method is:
1116%
1117%      MagickBooleanType PasskeyEncipherImage(Image *image,
1118%        const StringInfo *passkey,ExceptionInfo *exception)
1119%      MagickBooleanType EncipherImage(Image *image,const char *passphrase,
1120%        ExceptionInfo *exception)
1121%
1122%  A description of each parameter follows:
1123%
1124%    o passphrase: decipher cipher pixels with this passphrase.
1125%
1126%    o passkey: decrypt cipher pixels with this passkey.
1127%
1128%    o exception: return any errors or warnings in this structure.
1129%
1130*/
1131
1132MagickExport MagickBooleanType EncipherImage(Image *image,
1133  const char *passphrase,ExceptionInfo *exception)
1134{
1135  assert(image != (Image *) NULL);
1136  assert(image->signature == MagickSignature);
1137  if (image->debug != MagickFalse)
1138    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1139  assert(exception != (ExceptionInfo *) NULL);
1140  assert(exception->signature == MagickSignature);
1141  (void) passphrase;
1142  ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1143}
1144
1145MagickExport MagickBooleanType PasskeyEncipherImage(Image *image,
1146  const StringInfo *passkey,ExceptionInfo *exception)
1147{
1148  assert(image != (Image *) NULL);
1149  assert(image->signature == MagickSignature);
1150  if (image->debug != MagickFalse)
1151    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1152  assert(exception != (ExceptionInfo *) NULL);
1153  assert(exception->signature == MagickSignature);
1154  (void) passkey;
1155  ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
1156}
1157#endif
Note: See TracBrowser for help on using the browser.