/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 |