Coverage Report

Created: 2025-08-12 07:37

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