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