MagickCore 7.1.1
Convert, Edit, Or Compose Bitmap Images
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 "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#define AESBlocksize 16
69
70/*
71 Typedef declarations.
72*/
73typedef struct _AESInfo
74{
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*/
96static 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*/
167static AESInfo
168 *DestroyAESInfo(AESInfo *);
169
170static 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*/
192static AESInfo *AcquireAESInfo(void)
193{
194 AESInfo
195 *aes_info;
196
197 aes_info=(AESInfo *) AcquireCriticalMemory(sizeof(*aes_info));
198 (void) memset(aes_info,0,sizeof(*aes_info));
199 aes_info->blocksize=AESBlocksize;
200 aes_info->key=AcquireStringInfo(32);
201 aes_info->encipher_key=(unsigned int *) AcquireQuantumMemory(60UL,sizeof(
202 *aes_info->encipher_key));
203 aes_info->decipher_key=(unsigned int *) AcquireQuantumMemory(60UL,sizeof(
204 *aes_info->decipher_key));
205 if ((aes_info->key == (StringInfo *) NULL) ||
206 (aes_info->encipher_key == (unsigned int *) NULL) ||
207 (aes_info->decipher_key == (unsigned int *) NULL))
208 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
209 aes_info->timestamp=GetMagickTime();
210 aes_info->signature=MagickCoreSignature;
211 return(aes_info);
212}
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*/
236static AESInfo *DestroyAESInfo(AESInfo *aes_info)
237{
238 assert(aes_info != (AESInfo *) NULL);
239 assert(aes_info->signature == MagickCoreSignature);
240 if (IsEventLogging() != MagickFalse)
241 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
242 if (aes_info->decipher_key != (unsigned int *) NULL)
243 aes_info->decipher_key=(unsigned int *) RelinquishMagickMemory(
244 aes_info->decipher_key);
245 if (aes_info->encipher_key != (unsigned int *) NULL)
246 aes_info->encipher_key=(unsigned int *) RelinquishMagickMemory(
247 aes_info->encipher_key);
248 if (aes_info->key != (StringInfo *) NULL)
249 aes_info->key=DestroyStringInfo(aes_info->key);
250 aes_info->signature=(~MagickCoreSignature);
251 aes_info=(AESInfo *) RelinquishMagickMemory(aes_info);
252 return(aes_info);
253}
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
284static inline void AddRoundKey(const unsigned int *ciphertext,
285 const unsigned int *key,unsigned int *plaintext)
286{
287 ssize_t
288 i;
289
290 /*
291 Xor corresponding text input and round key input bytes.
292 */
293 for (i=0; i < 4; i++)
294 plaintext[i]=key[i] ^ ciphertext[i];
295}
296
297static inline unsigned int ByteMultiply(const unsigned char alpha,
298 const unsigned char beta)
299{
300 /*
301 Byte multiply two elements of GF(2^m) (mix columns and inverse mix columns).
302 */
303 if ((alpha == 0) || (beta == 0))
304 return(0);
305 return((unsigned int) InverseLog[(Log[alpha]+Log[beta]) % 0xff]);
306}
307
308static inline unsigned int ByteSubTransform(unsigned int x,
309 unsigned char *s_box)
310{
311 unsigned int
312 key;
313
314 /*
315 Non-linear layer resists differential and linear cryptoanalysis attacks.
316 */
317 key=((unsigned int) s_box[x & 0xff]) |
318 ((unsigned int) s_box[(x >> 8) & 0xff] << 8) |
319 ((unsigned int) s_box[(x >> 16) & 0xff] << 16) |
320 ((unsigned int) s_box[(x >> 24) & 0xff] << 24);
321 return(key);
322}
323
324static void FinalizeRoundKey(const unsigned int *ciphertext,
325 const unsigned int *key,unsigned char *plaintext)
326{
327 unsigned char
328 *p;
329
330 unsigned int
331 i,
332 j;
333
334 unsigned int
335 value;
336
337 /*
338 The round key is XORed with the result of the mix-column transformation.
339 */
340 p=plaintext;
341 for (i=0; i < 4; i++)
342 {
343 value=ciphertext[i] ^ key[i];
344 for (j=0; j < 4; j++)
345 *p++=(unsigned char) ((value >> (8*j)) & 0xff);
346 }
347 /*
348 Reset registers.
349 */
350 value=0;
351}
352
353static void InitializeRoundKey(const unsigned char *ciphertext,
354 const unsigned int *key,unsigned int *plaintext)
355{
356 const unsigned char
357 *p;
358
359 unsigned int
360 i,
361 j;
362
363 unsigned int
364 value;
365
366 p=ciphertext;
367 for (i=0; i < 4; i++)
368 {
369 value=0;
370 for (j=0; j < 4; j++)
371 value|=((unsigned int) *p++ << (8*j));
372 plaintext[i]=key[i] ^ value;
373 }
374 /*
375 Reset registers.
376 */
377 value=0;
378}
379
380static inline unsigned int RotateLeft(const unsigned int x)
381{
382 return(((x << 8) | ((x >> 24) & 0xff)));
383}
384
385static void EncipherAESBlock(AESInfo *aes_info,const unsigned char *plaintext,
386 unsigned char *ciphertext)
387{
388 ssize_t
389 i,
390 j;
391
392 static int
393 map[4][4] =
394 {
395 { 0, 1, 2, 3 },
396 { 1, 2, 3, 0 },
397 { 2, 3, 0, 1 },
398 { 3, 0, 1, 2 }
399 };
400
401 static unsigned int
402 D[] =
403 {
404 0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U, 0x0df2f2ffU,
405 0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U, 0x50303060U, 0x03010102U,
406 0xa96767ceU, 0x7d2b2b56U, 0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU,
407 0x9a7676ecU, 0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU,
408 0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU, 0xecadad41U,
409 0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U, 0xbf9c9c23U, 0xf7a4a453U,
410 0x967272e4U, 0x5bc0c09bU, 0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU,
411 0x6a26264cU, 0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U,
412 0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U, 0x937171e2U,
413 0x73d8d8abU, 0x53313162U, 0x3f15152aU, 0x0c040408U, 0x52c7c795U,
414 0x65232346U, 0x5ec3c39dU, 0x28181830U, 0xa1969637U, 0x0f05050aU,
415 0xb59a9a2fU, 0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU,
416 0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU, 0x1b090912U,
417 0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U, 0x2d1b1b36U, 0xb26e6edcU,
418 0xee5a5ab4U, 0xfba0a05bU, 0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U,
419 0xceb3b37dU, 0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U,
420 0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U, 0x60202040U,
421 0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U, 0xbe6a6ad4U, 0x46cbcb8dU,
422 0xd9bebe67U, 0x4b393972U, 0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U,
423 0x4acfcf85U, 0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU,
424 0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U, 0xcf45458aU,
425 0x10f9f9e9U, 0x06020204U, 0x817f7ffeU, 0xf05050a0U, 0x443c3c78U,
426 0xba9f9f25U, 0xe3a8a84bU, 0xf35151a2U, 0xfea3a35dU, 0xc0404080U,
427 0x8a8f8f05U, 0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U,
428 0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U, 0x30101020U,
429 0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU, 0x4ccdcd81U, 0x140c0c18U,
430 0x35131326U, 0x2fececc3U, 0xe15f5fbeU, 0xa2979735U, 0xcc444488U,
431 0x3917172eU, 0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU,
432 0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U, 0xa06060c0U,
433 0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U, 0x66222244U, 0x7e2a2a54U,
434 0xab90903bU, 0x8388880bU, 0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU,
435 0x3c141428U, 0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU,
436 0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U, 0xdb494992U,
437 0x0a06060cU, 0x6c242448U, 0xe45c5cb8U, 0x5dc2c29fU, 0x6ed3d3bdU,
438 0xefacac43U, 0xa66262c4U, 0xa8919139U, 0xa4959531U, 0x37e4e4d3U,
439 0x8b7979f2U, 0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU,
440 0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U, 0xb46c6cd8U,
441 0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU, 0xaf6565caU, 0x8e7a7af4U,
442 0xe9aeae47U, 0x18080810U, 0xd5baba6fU, 0x887878f0U, 0x6f25254aU,
443 0x722e2e5cU, 0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U,
444 0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU, 0xdd4b4b96U,
445 0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU, 0x907070e0U, 0x423e3e7cU,
446 0xc4b5b571U, 0xaa6666ccU, 0xd8484890U, 0x05030306U, 0x01f6f6f7U,
447 0x120e0e1cU, 0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U,
448 0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U, 0x38e1e1d9U,
449 0x13f8f8ebU, 0xb398982bU, 0x33111122U, 0xbb6969d2U, 0x70d9d9a9U,
450 0x898e8e07U, 0xa7949433U, 0xb69b9b2dU, 0x221e1e3cU, 0x92878715U,
451 0x20e9e9c9U, 0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U,
452 0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU, 0xdabfbf65U,
453 0x31e6e6d7U, 0xc6424284U, 0xb86868d0U, 0xc3414182U, 0xb0999929U,
454 0x772d2d5aU, 0x110f0f1eU, 0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU,
455 0x3a16162cU
456 };
457
458 unsigned int
459 alpha,
460 key[4],
461 text[4];
462
463 /*
464 Encipher one block.
465 */
466 (void) memset(text,0,sizeof(text));
467 InitializeRoundKey(plaintext,aes_info->encipher_key,text);
468 for (i=1; i < aes_info->rounds; i++)
469 {
470 /*
471 Linear mixing step: cause diffusion of the bits over multiple rounds.
472 */
473 for (j=0; j < 4; j++)
474 key[j]=D[text[j] & 0xff] ^
475 RotateLeft(D[(text[map[1][j]] >> 8) & 0xff] ^
476 RotateLeft(D[(text[map[2][j]] >> 16) & 0xff] ^
477 RotateLeft(D[(text[map[3][j]] >> 24) & 0xff])));
478 AddRoundKey(key,aes_info->encipher_key+4*i,text);
479 }
480 for (i=0; i < 4; i++)
481 {
482 alpha=(text[i] & 0x000000ff) | ((text[map[1][i]]) & 0x0000ff00) |
483 ((text[map[2][i]]) & 0x00ff0000) | ((text[map[3][i]]) & 0xff000000);
484 key[i]=ByteSubTransform(alpha,SBox);
485 }
486 FinalizeRoundKey(key,aes_info->encipher_key+4*aes_info->rounds,ciphertext);
487 /*
488 Reset registers.
489 */
490 alpha=0;
491 (void) ResetMagickMemory(key,0,sizeof(key));
492 (void) ResetMagickMemory(text,0,sizeof(text));
493}
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
527static inline void IncrementCipherNonce(const size_t length,
528 unsigned char *nonce)
529{
530 ssize_t
531 i;
532
533 for (i=(ssize_t) (length-1); i >= 0; i--)
534 {
535 nonce[i]++;
536 if (nonce[i] != 0)
537 return;
538 }
539 ThrowFatalException(ResourceLimitFatalError,"Sequence wrap error `%s'");
540}
541
542MagickExport MagickBooleanType DecipherImage(Image *image,
543 const char *passphrase,ExceptionInfo *exception)
544{
545 MagickBooleanType
546 status;
547
549 *passkey;
550
551 if (passphrase == (const char *) NULL)
552 return(MagickTrue);
553 passkey=StringToStringInfo(passphrase);
554 if (passkey == (StringInfo *) NULL)
555 return(MagickFalse);
556 status=PasskeyDecipherImage(image,passkey,exception);
557 passkey=DestroyStringInfo(passkey);
558 return(status);
559}
560
561MagickExport MagickBooleanType PasskeyDecipherImage(Image *image,
562 const StringInfo *passkey,ExceptionInfo *exception)
563{
564#define DecipherImageTag "Decipher/Image "
565
566 AESInfo
567 *aes_info;
568
570 *image_view;
571
572 const unsigned char
573 *digest;
574
575 MagickBooleanType
576 proceed;
577
578 MagickSizeType
579 extent;
580
582 *quantum_info;
583
584 QuantumType
585 quantum_type;
586
588 *signature_info;
589
590 unsigned char
591 *p;
592
593 size_t
594 length;
595
596 ssize_t
597 y;
598
600 *key,
601 *nonce;
602
603 unsigned char
604 input_block[AESBlocksize],
605 output_block[AESBlocksize],
606 *pixels;
607
608 /*
609 Generate decipher key and nonce.
610 */
611 assert(image != (Image *) NULL);
612 assert(image->signature == MagickCoreSignature);
613 assert(exception != (ExceptionInfo *) NULL);
614 assert(exception->signature == MagickCoreSignature);
615 if (IsEventLogging() != MagickFalse)
616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
617 if (passkey == (const StringInfo *) NULL)
618 return(MagickTrue);
619 aes_info=AcquireAESInfo();
620 key=CloneStringInfo(passkey);
621 if (key == (StringInfo *) NULL)
622 {
623 aes_info=DestroyAESInfo(aes_info);
624 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
625 image->filename);
626 }
627 nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
628 if (nonce == (StringInfo *) NULL)
629 {
630 key=DestroyStringInfo(key);
631 aes_info=DestroyAESInfo(aes_info);
632 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
633 image->filename);
634 }
635 SetAESKey(aes_info,key);
636 key=DestroyStringInfo(key);
637 signature_info=AcquireSignatureInfo();
638 UpdateSignature(signature_info,nonce);
639 extent=(MagickSizeType) image->columns*image->rows;
640 SetStringInfoLength(nonce,sizeof(extent));
641 SetStringInfoDatum(nonce,(const unsigned char *) &extent);
642 UpdateSignature(signature_info,nonce);
643 nonce=DestroyStringInfo(nonce);
644 FinalizeSignature(signature_info);
645 (void) memset(input_block,0,sizeof(input_block));
646 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
647 (void) memcpy(input_block,digest,MagickMin(AESBlocksize,
648 GetSignatureDigestsize(signature_info))*sizeof(*input_block));
649 signature_info=DestroySignatureInfo(signature_info);
650 /*
651 Convert cipher pixels to plain pixels.
652 */
653 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
654 if (quantum_info == (QuantumInfo *) NULL)
655 {
656 aes_info=DestroyAESInfo(aes_info);
657 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
658 image->filename);
659 }
660 quantum_type=GetQuantumType(image,exception);
661 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
662 image_view=AcquireAuthenticCacheView(image,exception);
663 for (y=0; y < (ssize_t) image->rows; y++)
664 {
665 ssize_t
666 i,
667 x;
668
669 Quantum
670 *magick_restrict q;
671
672 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
673 if (q == (Quantum *) NULL)
674 break;
675 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type,
676 pixels,exception);
677 p=pixels;
678 for (x=0; x < (ssize_t) length; x+=AESBlocksize)
679 {
680 (void) memcpy(output_block,input_block,AESBlocksize*
681 sizeof(*output_block));
682 IncrementCipherNonce(AESBlocksize,input_block);
683 EncipherAESBlock(aes_info,output_block,output_block);
684 for (i=0; i < AESBlocksize; i++)
685 p[i]^=output_block[i];
686 p+=AESBlocksize;
687 }
688 (void) memcpy(output_block,input_block,AESBlocksize*
689 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,exception) == 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 signature=StringInfoToHexString(GetSignatureDigest(signature_info));
861 (void) SetImageProperty(image,"cipher:type","AES",exception);
862 (void) SetImageProperty(image,"cipher:mode","CTR",exception);
863 (void) SetImageProperty(image,"cipher:nonce",signature,exception);
864 signature=DestroyString(signature);
865 (void) memset(input_block,0,sizeof(input_block));
866 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
867 (void) memcpy(input_block,digest,MagickMin(AESBlocksize,
868 GetSignatureDigestsize(signature_info))*sizeof(*input_block));
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=(unsigned char *) 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
889 Quantum
890 *magick_restrict q;
891
892 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
893 if (q == (Quantum *) 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) memcpy(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+=AESBlocksize;
907 }
908 (void) memcpy(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