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