cipher.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                   CCCC  IIIII  PPPP   H   H  EEEEE  RRRR                    %
00006 %                  C        I    P   P  H   H  E      R   R                   %
00007 %                  C        I    PPPP   HHHHH  EEE    RRRR                    %
00008 %                  C        I    P      H   H  E      R R                     %
00009 %                   CCCC  IIIII  P      H   H  EEEEE  R  R                    %
00010 %                                                                             %
00011 %                                                                             %
00012 %                          MagickCore Cipher Methods                          %
00013 %                                                                             %
00014 %                             Software Design                                 %
00015 %                               John Cristy                                   %
00016 %                               March  2003                                   %
00017 %                                                                             %
00018 %                                                                             %
00019 %  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
00020 %  dedicated to making software imaging solutions freely available.           %
00021 %                                                                             %
00022 %  You may not use this file except in compliance with the License.  You may  %
00023 %  obtain a copy of the License at                                            %
00024 %                                                                             %
00025 %    http://www.imagemagick.org/script/license.php                            %
00026 %                                                                             %
00027 %  Unless required by applicable law or agreed to in writing, software        %
00028 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00029 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00030 %  See the License for the specific language governing permissions and        %
00031 %  limitations under the License.                                             %
00032 %                                                                             %
00033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00034 %
00035 %
00036 */
00037 
00038 /*
00039   Include declarations.
00040 */
00041 #include "magick/studio.h"
00042 #include "magick/cache.h"
00043 #include "magick/cipher.h"
00044 #include "magick/exception.h"
00045 #include "magick/exception-private.h"
00046 #include "magick/hashmap.h"
00047 #include "magick/image.h"
00048 #include "magick/image-private.h"
00049 #include "magick/list.h"
00050 #include "magick/memory_.h"
00051 #include "magick/monitor.h"
00052 #include "magick/monitor-private.h"
00053 #include "magick/property.h"
00054 #include "magick/quantum-private.h"
00055 #include "magick/registry.h"
00056 #include "magick/semaphore.h"
00057 #include "magick/signature-private.h"
00058 #include "magick/splay-tree.h"
00059 #include "magick/statistic.h"
00060 #include "magick/string_.h"
00061 
00062 #if defined(MAGICKCORE_CIPHER_SUPPORT)
00063 /*
00064   Define declarations.
00065 */
00066 #define AESBlocksize 16
00067 
00068 /*
00069   Typedef declarations.
00070 */
00071 typedef struct _AESInfo
00072 {
00073   StringInfo
00074     *key;
00075 
00076   unsigned int
00077     blocksize,
00078     *encipher_key,
00079     *decipher_key;
00080 
00081   long
00082     rounds,
00083     timestamp;
00084 
00085   unsigned long
00086     signature;
00087 } AESInfo;
00088 
00089 /*
00090   Global declarations.
00091 */
00092 static unsigned char
00093   InverseLog[256] =
00094   {
00095       1,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,
00096      19,  53,  95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,
00097      30,  34, 102, 170, 229,  52,  92, 228,  55,  89, 235,  38, 106, 190,
00098     217, 112, 144, 171, 230,  49,  83, 245,   4,  12,  20,  60,  68, 204,
00099      79, 209, 104, 184, 211, 110, 178, 205,  76, 212, 103, 169, 224,  59,
00100      77, 215,  98, 166, 241,   8,  24,  40, 120, 136, 131, 158, 185, 208,
00101     107, 189, 220, 127, 129, 152, 179, 206,  73, 219, 118, 154, 181, 196,
00102      87, 249,  16,  48,  80, 240,  11,  29,  39, 105, 187, 214,  97, 163,
00103     254,  25,  43, 125, 135, 146, 173, 236,  47, 113, 147, 174, 233,  32,
00104      96, 160, 251,  22,  58,  78, 210, 109, 183, 194,  93, 231,  50,  86,
00105     250,  21,  63,  65, 195,  94, 226,  61,  71, 201,  64, 192,  91, 237,
00106      44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239,  42, 126,
00107     130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193,  88, 232,  35,
00108     101, 175, 234,  37, 111, 177, 200,  67, 197,  84, 252,  31,  33,  99,
00109     165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,  69, 207,
00110      74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,
00111      18,  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,
00112      13,  23,  57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180,
00113     199,  82, 246,   1
00114   },
00115   Log[256] =
00116   {
00117       0,   0,  25,   1,  50,   2,  26, 198,  75, 199,  27, 104,  51, 238,
00118     223,   3, 100,   4, 224,  14,  52, 141, 129, 239,  76, 113,   8, 200,
00119     248, 105,  28, 193, 125, 194,  29, 181, 249, 185,  39, 106,  77, 228,
00120     166, 114, 154, 201,   9, 120, 101,  47, 138,   5,  33,  15, 225,  36,
00121      18, 240, 130,  69,  53, 147, 218, 142, 150, 143, 219, 189,  54, 208,
00122     206, 148,  19,  92, 210, 241,  64,  70, 131,  56, 102, 221, 253,  48,
00123     191,   6, 139,  98, 179,  37, 226, 152,  34, 136, 145,  16, 126, 110,
00124      72, 195, 163, 182,  30,  66,  58, 107,  40,  84, 250, 133,  61, 186,
00125      43, 121,  10,  21, 155, 159,  94, 202,  78, 212, 172, 229, 243, 115,
00126     167,  87, 175,  88, 168,  80, 244, 234, 214, 116,  79, 174, 233, 213,
00127     231, 230, 173, 232,  44, 215, 117, 122, 235,  22,  11, 245,  89, 203,
00128      95, 176, 156, 169,  81, 160, 127,  12, 246, 111,  23, 196,  73, 236,
00129     216,  67,  31,  45, 164, 118, 123, 183, 204, 187,  62,  90, 251,  96,
00130     177, 134,  59,  82, 161, 108, 170,  85,  41, 157, 151, 178, 135, 144,
00131      97, 190, 220, 252, 188, 149, 207, 205,  55,  63,  91, 209,  83,  57,
00132     132, 60,   65, 162, 109,  71,  20,  42, 158,  93,  86, 242, 211, 171,
00133      68,  17, 146, 217,  35,  32,  46, 137, 180, 124, 184,  38, 119, 153,
00134     227, 165, 103,  74, 237, 222, 197,  49, 254,  24,  13,  99, 140, 128,
00135     192, 247, 112,   7,
00136   },
00137   SBox[256] =
00138   {
00139      99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215,
00140     171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175,
00141     156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165,
00142     229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,
00143       7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110,
00144      90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237,
00145      32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239,
00146     170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
00147      81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255,
00148     243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61,
00149     100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238,
00150     184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92,
00151     194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
00152      78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46,
00153      28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62,
00154     181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
00155     225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,
00156      40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15,
00157     176,  84, 187, 22
00158   };
00159 
00160 /*
00161   Forward declarations.
00162 */
00163 static AESInfo
00164   *DestroyAESInfo(AESInfo *);
00165 
00166 static void
00167   EncipherAESBlock(AESInfo *,const unsigned char *,unsigned char *),
00168   SetAESKey(AESInfo *,const StringInfo *);
00169 
00170 /*
00171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00172 %                                                                             %
00173 %                                                                             %
00174 %                                                                             %
00175 %   A c q u i r e A E S I n f o                                               %
00176 %                                                                             %
00177 %                                                                             %
00178 %                                                                             %
00179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00180 %
00181 %  AcquireAESInfo() allocate the AESInfo structure.
00182 %
00183 %  The format of the AcquireAESInfo method is:
00184 %
00185 %      AESInfo *AcquireAESInfo(void)
00186 %
00187 */
00188 static AESInfo *AcquireAESInfo(void)
00189 {
00190   AESInfo
00191     *aes_info;
00192 
00193   aes_info=(AESInfo *) AcquireMagickMemory(sizeof(*aes_info));
00194   if (aes_info == (AESInfo *) NULL)
00195     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00196   (void) ResetMagickMemory(aes_info,0,sizeof(*aes_info));
00197   aes_info->blocksize=AESBlocksize;
00198   aes_info->key=AcquireStringInfo(32);
00199   aes_info->encipher_key=(unsigned int *) AcquireQuantumMemory(60UL,sizeof(
00200     *aes_info->encipher_key));
00201   aes_info->decipher_key=(unsigned int *) AcquireQuantumMemory(60UL,sizeof(
00202     *aes_info->decipher_key));
00203   if ((aes_info->key == (StringInfo *) NULL) ||
00204       (aes_info->encipher_key == (unsigned int *) NULL) ||
00205       (aes_info->decipher_key == (unsigned int *) NULL))
00206     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00207   aes_info->timestamp=(long) time(0);
00208   aes_info->signature=MagickSignature;
00209   return(aes_info);
00210 }
00211 
00212 /*
00213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00214 %                                                                             %
00215 %                                                                             %
00216 %                                                                             %
00217 %     D e c i p h e r I m a g e                                               %
00218 %                                                                             %
00219 %                                                                             %
00220 %                                                                             %
00221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00222 %
00223 %  DecipherImage() converts cipher pixels to plain pixels.
00224 %
00225 %  The format of the DecipherImage method is:
00226 %
00227 %      MagickBooleanType DecipherImage(Image *image,const char *passphrase,
00228 %        ExceptionInfo *exception)
00229 %
00230 %  A description of each parameter follows:
00231 %
00232 %    o image: the image.
00233 %
00234 %    o passphrase: decipher cipher pixels with this passphrase.
00235 %
00236 %    o exception: return any errors or warnings in this structure.
00237 %
00238 */
00239 
00240 static inline size_t MagickMin(const size_t x,const size_t y)
00241 {
00242   if (x < y)
00243     return(x);
00244   return(y);
00245 }
00246 
00247 MagickExport MagickBooleanType DecipherImage(Image *image,
00248   const char *passphrase,ExceptionInfo *exception)
00249 {
00250 #define DecipherImageTag  "Decipher/Image "
00251 
00252   AESInfo
00253     *aes_info;
00254 
00255   const unsigned char
00256     *digest;
00257 
00258   IndexPacket
00259     *indexes;
00260 
00261   long
00262     y;
00263 
00264   MagickBooleanType
00265     proceed;
00266 
00267   QuantumInfo
00268     *quantum_info;
00269 
00270   QuantumType
00271     quantum_type;
00272 
00273   register long
00274     x;
00275 
00276   register PixelPacket
00277     *q;
00278 
00279   register unsigned char
00280     *p;
00281 
00282   SignatureInfo
00283     *signature_info;
00284 
00285   size_t
00286     length;
00287 
00288   StringInfo
00289     *key,
00290     *nonce;
00291 
00292   unsigned char
00293     input_block[AESBlocksize],
00294     output_block[AESBlocksize],
00295     *pixels;
00296 
00297   /*
00298     Generate decipher key and nonce.
00299   */
00300   assert(image != (Image *) NULL);
00301   assert(image->signature == MagickSignature);
00302   if (image->debug != MagickFalse)
00303     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00304   assert(exception != (ExceptionInfo *) NULL);
00305   assert(exception->signature == MagickSignature);
00306   if (passphrase == (const char *) NULL)
00307     return(MagickTrue);
00308   quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
00309   if (quantum_info == (QuantumInfo *) NULL)
00310     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00311       image->filename);
00312   aes_info=AcquireAESInfo();
00313   key=StringToStringInfo(passphrase);
00314   if (key == (StringInfo *) NULL)
00315     {
00316       aes_info=DestroyAESInfo(aes_info);
00317       quantum_info=DestroyQuantumInfo(quantum_info);
00318       return(MagickFalse);
00319     }
00320   nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
00321   if (nonce == (StringInfo *) NULL)
00322     {
00323       key=DestroyStringInfo(key);
00324       aes_info=DestroyAESInfo(aes_info);
00325       quantum_info=DestroyQuantumInfo(quantum_info);
00326       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00327         image->filename);
00328     }
00329   SetAESKey(aes_info,key);
00330   key=DestroyStringInfo(key);
00331   signature_info=AcquireSignatureInfo();
00332   UpdateSignature(signature_info,nonce);
00333   SetStringInfoLength(nonce,sizeof(quantum_info->extent));
00334   SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
00335   UpdateSignature(signature_info,nonce);
00336   FinalizeSignature(signature_info);
00337   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
00338   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
00339   (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
00340     GetSignatureDigestsize(signature_info))*sizeof(*input_block));
00341   nonce=DestroyStringInfo(nonce);
00342   signature_info=DestroySignatureInfo(signature_info);
00343   /*
00344     Convert cipher pixels to plain pixels.
00345   */
00346   quantum_type=GetQuantumType(image,exception);
00347   pixels=GetQuantumPixels(quantum_info);
00348   for (y=0; y < (long) image->rows; y++)
00349   {
00350     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
00351     if (q == (PixelPacket *) NULL)
00352       break;
00353     indexes=GetAuthenticIndexQueue(image);
00354     length=ExportQuantumPixels(image,(const ViewInfo *) NULL,quantum_info,
00355       quantum_type,pixels,exception);
00356     p=pixels;
00357     for (x=0; x < (long) length; x++)
00358     {
00359       (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
00360         sizeof(*output_block));
00361       EncipherAESBlock(aes_info,output_block,output_block); 
00362       (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
00363         sizeof(*input_block));
00364       input_block[AESBlocksize-1]=(*p);
00365       *p++^=(*output_block);
00366     }
00367     (void) ImportQuantumPixels(image,(ViewInfo *) NULL,quantum_info,
00368       quantum_type,pixels,exception);
00369     if (SyncAuthenticPixels(image,exception) == MagickFalse)
00370       break;
00371     proceed=SetImageProgress(image,DecipherImageTag,y,image->rows);
00372     if (proceed == MagickFalse)
00373       break;
00374   }
00375   (void) DeleteImageProperty(image,"cipher:type");
00376   (void) DeleteImageProperty(image,"cipher:mode");
00377   (void) DeleteImageProperty(image,"cipher:nonce");
00378   image->taint=MagickFalse;
00379   /*
00380     Free resources.
00381   */
00382   quantum_info=DestroyQuantumInfo(quantum_info);
00383   aes_info=DestroyAESInfo(aes_info);
00384   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
00385   (void) ResetMagickMemory(output_block,0,sizeof(output_block));
00386   return(y == (long) image->rows ? MagickTrue : MagickFalse);
00387 }
00388 
00389 /*
00390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00391 %                                                                             %
00392 %                                                                             %
00393 %                                                                             %
00394 %   D e s t r o y A E S I n f o                                               %
00395 %                                                                             %
00396 %                                                                             %
00397 %                                                                             %
00398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00399 %
00400 %  DestroyAESInfo() zeros memory associated with the AESInfo structure.
00401 %
00402 %  The format of the DestroyAESInfo method is:
00403 %
00404 %      AESInfo *DestroyAESInfo(AESInfo *aes_info)
00405 %
00406 %  A description of each parameter follows:
00407 %
00408 %    o aes_info: the cipher context.
00409 %
00410 */
00411 static AESInfo *DestroyAESInfo(AESInfo *aes_info)
00412 {
00413   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00414   assert(aes_info != (AESInfo *) NULL);
00415   assert(aes_info->signature == MagickSignature);
00416   if (aes_info->decipher_key != (unsigned int *) NULL)
00417     aes_info->decipher_key=(unsigned int *) RelinquishMagickMemory(
00418       aes_info->decipher_key);
00419   if (aes_info->encipher_key != (unsigned int *) NULL)
00420     aes_info->encipher_key=(unsigned int *) RelinquishMagickMemory(
00421       aes_info->encipher_key);
00422   if (aes_info->key != (StringInfo *) NULL)
00423     aes_info->key=DestroyStringInfo(aes_info->key);
00424   aes_info->signature=(~MagickSignature);
00425   aes_info=(AESInfo *) RelinquishMagickMemory(aes_info);
00426   return(aes_info);
00427 }
00428 
00429 /*
00430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00431 %                                                                             %
00432 %                                                                             %
00433 %                                                                             %
00434 %     E n c i p h e r I m a g e                                               %
00435 %                                                                             %
00436 %                                                                             %
00437 %                                                                             %
00438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00439 %
00440 %  EncipherImage() converts pixels to cipher-pixels.
00441 %
00442 %  The format of the EncipherImage method is:
00443 %
00444 %      MagickBooleanType EncipherImage(Image *image,const char *passphrase,
00445 %        ExceptionInfo *exception)
00446 %
00447 %  A description of each parameter follows:
00448 %
00449 %    o image: the image.
00450 %
00451 %    o passphrase: encipher pixels with this passphrase.
00452 %
00453 %    o exception: return any errors or warnings in this structure.
00454 %
00455 */
00456 MagickExport MagickBooleanType EncipherImage(Image *image,
00457   const char *passphrase,ExceptionInfo *exception)
00458 {
00459 #define EncipherImageTag  "Encipher/Image "
00460 
00461   AESInfo
00462     *aes_info;
00463 
00464   char
00465     *signature;
00466 
00467   const unsigned char
00468     *digest;
00469 
00470   IndexPacket
00471     *indexes;
00472 
00473   long
00474     y;
00475 
00476   MagickBooleanType
00477     proceed;
00478 
00479   QuantumInfo
00480     *quantum_info;
00481 
00482   QuantumType
00483     quantum_type;
00484 
00485   register long
00486     x;
00487 
00488   register PixelPacket
00489     *q;
00490 
00491   register unsigned char
00492     *p;
00493 
00494   SignatureInfo
00495     *signature_info;
00496 
00497   size_t
00498     length;
00499 
00500   StringInfo
00501     *key,
00502     *nonce;
00503 
00504   unsigned char
00505     input_block[AESBlocksize],
00506     output_block[AESBlocksize],
00507     *pixels;
00508 
00509   /*
00510     Generate encipher key and nonce.
00511   */
00512   assert(image != (Image *) NULL);
00513   assert(image->signature == MagickSignature);
00514   if (image->debug != MagickFalse)
00515     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00516   assert(exception != (ExceptionInfo *) NULL);
00517   assert(exception->signature == MagickSignature);
00518   if (passphrase == (const char *) NULL)
00519     return(MagickTrue);
00520   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00521     return(MagickFalse);
00522   quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
00523   if (quantum_info == (QuantumInfo *) NULL)
00524     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00525       image->filename);
00526   aes_info=AcquireAESInfo();
00527   key=StringToStringInfo(passphrase);
00528   if (key == (StringInfo *) NULL)
00529     {
00530       aes_info=DestroyAESInfo(aes_info);
00531       quantum_info=DestroyQuantumInfo(quantum_info);
00532       return(MagickFalse);
00533     }
00534   nonce=SplitStringInfo(key,GetStringInfoLength(key)/2);
00535   if (nonce == (StringInfo *) NULL)
00536     {
00537       key=DestroyStringInfo(key);
00538       aes_info=DestroyAESInfo(aes_info);
00539       quantum_info=DestroyQuantumInfo(quantum_info);
00540       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00541         image->filename);
00542     }
00543   SetAESKey(aes_info,key);
00544   key=DestroyStringInfo(key);
00545   signature_info=AcquireSignatureInfo();
00546   UpdateSignature(signature_info,nonce);
00547   SetStringInfoLength(nonce,sizeof(quantum_info->extent));
00548   SetStringInfoDatum(nonce,(const unsigned char *) &quantum_info->extent);
00549   UpdateSignature(signature_info,nonce);
00550   nonce=DestroyStringInfo(nonce);
00551   FinalizeSignature(signature_info);
00552   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
00553   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
00554   (void) CopyMagickMemory(input_block,digest,MagickMin(AESBlocksize,
00555     GetSignatureDigestsize(signature_info))*sizeof(*input_block));
00556   signature=StringInfoToHexString(GetSignatureDigest(signature_info));
00557   (void) SetImageProperty(image,"cipher:type","AES");
00558   (void) SetImageProperty(image,"cipher:mode","CFB");
00559   (void) SetImageProperty(image,"cipher:nonce",signature);
00560   signature=DestroyString(signature);
00561   signature_info=DestroySignatureInfo(signature_info);
00562   /*
00563     Convert plain pixels to cipher pixels.
00564   */
00565   quantum_type=GetQuantumType(image,exception);
00566   pixels=GetQuantumPixels(quantum_info);
00567   for (y=0; y < (long) image->rows; y++)
00568   {
00569     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
00570     if (q == (PixelPacket *) NULL)
00571       break;
00572     indexes=GetAuthenticIndexQueue(image);
00573     length=ExportQuantumPixels(image,(const ViewInfo *) NULL,quantum_info,
00574       quantum_type,pixels,exception);
00575     p=pixels;
00576     for (x=0; x < (long) length; x++)
00577     {
00578       (void) CopyMagickMemory(output_block,input_block,AESBlocksize*
00579         sizeof(*output_block));
00580       EncipherAESBlock(aes_info,output_block,output_block); 
00581       *p^=(*output_block);
00582       (void) CopyMagickMemory(input_block,input_block+1,(AESBlocksize-1)*
00583         sizeof(*input_block));
00584       input_block[AESBlocksize-1]=(*p++);
00585     }
00586     (void) ImportQuantumPixels(image,(ViewInfo *) NULL,quantum_info,
00587       quantum_type,pixels,exception);
00588     if (SyncAuthenticPixels(image,exception) == MagickFalse)
00589       break;
00590     proceed=SetImageProgress(image,EncipherImageTag,y,image->rows);
00591     if (proceed == MagickFalse)
00592       break;
00593   }
00594   image->taint=MagickFalse;
00595   /*
00596     Free resources.
00597   */
00598   quantum_info=DestroyQuantumInfo(quantum_info);
00599   aes_info=DestroyAESInfo(aes_info);
00600   (void) ResetMagickMemory(input_block,0,sizeof(input_block));
00601   (void) ResetMagickMemory(output_block,0,sizeof(output_block));
00602   return(y == (long) image->rows ? MagickTrue : MagickFalse);
00603 }
00604 
00605 /*
00606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00607 %                                                                             %
00608 %                                                                             %
00609 %                                                                             %
00610 %   E n c i p h e r A E S B l o c k                                           %
00611 %                                                                             %
00612 %                                                                             %
00613 %                                                                             %
00614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00615 %
00616 %  EncipherAESBlock() enciphers a single block of plaintext to produce a block
00617 %  of ciphertext.
00618 %
00619 %  The format of the EncipherAESBlock method is:
00620 %
00621 %      void EncipherAES(AESInfo *aes_info,const unsigned char *plaintext,
00622 %        unsigned char *ciphertext)
00623 %
00624 %  A description of each parameter follows:
00625 %
00626 %    o aes_info: the cipher context.
00627 %
00628 %    o plaintext: the plain text.
00629 %
00630 %    o ciphertext: the cipher text.
00631 %
00632 */
00633 
00634 static inline void AddRoundKey(const unsigned int *ciphertext,
00635   const unsigned int *key,unsigned int *plaintext)
00636 {
00637   register long
00638     i;
00639 
00640   /*
00641     Xor corresponding text input and round key input bytes.
00642   */
00643   for (i=0; i < 4; i++)
00644     plaintext[i]=key[i] ^ ciphertext[i];
00645 }
00646 
00647 static inline unsigned char ByteMultiply(const unsigned char alpha,
00648   const unsigned char beta)
00649 {
00650   /*
00651     Byte multiply two elements of GF(2^m) (mix columns and inverse mix columns).
00652   */
00653   if ((alpha == 0) || (beta == 0))
00654     return(0);
00655   return(InverseLog[(Log[alpha]+Log[beta]) % 0xff]);
00656 }
00657 
00658 static inline unsigned int ByteSubTransform(unsigned int x,
00659   unsigned char *s_box)
00660 {
00661   unsigned int
00662     key;
00663 
00664   /*
00665     Non-linear layer resists differential and linear cryptoanalysis attacks.
00666   */
00667   key=(s_box[x & 0xff]) | (s_box[(x >> 8) & 0xff] << 8) |
00668     (s_box[(x >> 16) & 0xff] << 16) | (s_box[(x >> 24) & 0xff] << 24);
00669   return(key);
00670 }
00671 
00672 static void FinalizeRoundKey(const unsigned int *ciphertext,
00673   const unsigned int *key,unsigned char *plaintext)
00674 {
00675   register unsigned char
00676     *p;
00677 
00678   register unsigned int
00679     i,
00680     j;
00681 
00682   unsigned int
00683     value;
00684 
00685   /*
00686     The round key is XORed with the result of the mix-column transformation.
00687   */
00688   p=plaintext;
00689   for (i=0; i < 4; i++)
00690   {
00691     value=ciphertext[i] ^ key[i];
00692     for (j=0; j < 4; j++)
00693       *p++=(value >> (8*j)) & 0xff;
00694   }
00695   /*
00696     Reset registers.
00697   */
00698   value=0;
00699 }
00700 
00701 static void InitializeRoundKey(const unsigned char *ciphertext,
00702   const unsigned int *key,unsigned int *plaintext)
00703 {
00704   register const unsigned char
00705     *p;
00706 
00707   register unsigned int
00708     i,
00709     j;
00710 
00711   unsigned int
00712     value;
00713 
00714   p=ciphertext;
00715   for (i=0; i < 4; i++)
00716   {
00717     value=0;
00718     for (j=0; j < 4; j++)
00719       value|=(*p++ << (8*j));
00720     plaintext[i]=key[i] ^ value;
00721   }
00722   /*
00723     Reset registers.
00724   */
00725   value=0;
00726 }
00727 
00728 static inline unsigned int RotateLeft(const unsigned int x)
00729 {
00730   return(((x << 8) | ((x >> 24) & 0xff)));
00731 }
00732 
00733 static void EncipherAESBlock(AESInfo *aes_info,const unsigned char *plaintext,
00734   unsigned char *ciphertext)
00735 {
00736   register long
00737     i,
00738     j;
00739 
00740   static int
00741     map[4][4] =
00742     {
00743       { 0, 1, 2, 3 },
00744       { 1, 2, 3, 0 },
00745       { 2, 3, 0, 1 },
00746       { 3, 0, 1, 2 }
00747     };
00748 
00749   static unsigned int
00750     D[] =
00751     {
00752       0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U, 0x0df2f2ffU,
00753       0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U, 0x50303060U, 0x03010102U,
00754       0xa96767ceU, 0x7d2b2b56U, 0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU,
00755       0x9a7676ecU, 0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU,
00756       0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU, 0xecadad41U,
00757       0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U, 0xbf9c9c23U, 0xf7a4a453U,
00758       0x967272e4U, 0x5bc0c09bU, 0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU,
00759       0x6a26264cU, 0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U,
00760       0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U, 0x937171e2U,
00761       0x73d8d8abU, 0x53313162U, 0x3f15152aU, 0x0c040408U, 0x52c7c795U,
00762       0x65232346U, 0x5ec3c39dU, 0x28181830U, 0xa1969637U, 0x0f05050aU,
00763       0xb59a9a2fU, 0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU,
00764       0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU, 0x1b090912U,
00765       0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U, 0x2d1b1b36U, 0xb26e6edcU,
00766       0xee5a5ab4U, 0xfba0a05bU, 0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U,
00767       0xceb3b37dU, 0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U,
00768       0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U, 0x60202040U,
00769       0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U, 0xbe6a6ad4U, 0x46cbcb8dU,
00770       0xd9bebe67U, 0x4b393972U, 0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U,
00771       0x4acfcf85U, 0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU,
00772       0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U, 0xcf45458aU,
00773       0x10f9f9e9U, 0x06020204U, 0x817f7ffeU, 0xf05050a0U, 0x443c3c78U,
00774       0xba9f9f25U, 0xe3a8a84bU, 0xf35151a2U, 0xfea3a35dU, 0xc0404080U,
00775       0x8a8f8f05U, 0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U,
00776       0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U, 0x30101020U,
00777       0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU, 0x4ccdcd81U, 0x140c0c18U,
00778       0x35131326U, 0x2fececc3U, 0xe15f5fbeU, 0xa2979735U, 0xcc444488U,
00779       0x3917172eU, 0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU,
00780       0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U, 0xa06060c0U,
00781       0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U, 0x66222244U, 0x7e2a2a54U,
00782       0xab90903bU, 0x8388880bU, 0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU,
00783       0x3c141428U, 0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU,
00784       0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U, 0xdb494992U,
00785       0x0a06060cU, 0x6c242448U, 0xe45c5cb8U, 0x5dc2c29fU, 0x6ed3d3bdU,
00786       0xefacac43U, 0xa66262c4U, 0xa8919139U, 0xa4959531U, 0x37e4e4d3U,
00787       0x8b7979f2U, 0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU,
00788       0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U, 0xb46c6cd8U,
00789       0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU, 0xaf6565caU, 0x8e7a7af4U,
00790       0xe9aeae47U, 0x18080810U, 0xd5baba6fU, 0x887878f0U, 0x6f25254aU,
00791       0x722e2e5cU, 0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U,
00792       0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU, 0xdd4b4b96U,
00793       0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU, 0x907070e0U, 0x423e3e7cU,
00794       0xc4b5b571U, 0xaa6666ccU, 0xd8484890U, 0x05030306U, 0x01f6f6f7U,
00795       0x120e0e1cU, 0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U,
00796       0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U, 0x38e1e1d9U,
00797       0x13f8f8ebU, 0xb398982bU, 0x33111122U, 0xbb6969d2U, 0x70d9d9a9U,
00798       0x898e8e07U, 0xa7949433U, 0xb69b9b2dU, 0x221e1e3cU, 0x92878715U,
00799       0x20e9e9c9U, 0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U,
00800       0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU, 0xdabfbf65U,
00801       0x31e6e6d7U, 0xc6424284U, 0xb86868d0U, 0xc3414182U, 0xb0999929U,
00802       0x772d2d5aU, 0x110f0f1eU, 0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU,
00803       0x3a16162cU
00804     };
00805 
00806   unsigned int
00807     alpha,
00808     key[4],
00809     text[4];
00810 
00811   /*
00812     Encipher one block.
00813   */
00814   (void) memset(text,0,sizeof(text));
00815   InitializeRoundKey(plaintext,aes_info->encipher_key,text);
00816   for (i=1; i < aes_info->rounds; i++)
00817   {
00818     /*
00819       Linear mixing step: cause diffusion of the bits over multiple rounds.
00820     */
00821     for (j=0; j < 4; j++)
00822       key[j]=D[text[j] & 0xff] ^
00823         RotateLeft(D[(text[map[1][j]] >> 8) & 0xff] ^
00824         RotateLeft(D[(text[map[2][j]] >> 16) & 0xff] ^
00825         RotateLeft(D[(text[map[3][j]] >> 24) & 0xff])));
00826     AddRoundKey(key,aes_info->encipher_key+4*i,text);
00827   }
00828   for (i=0; i < 4; i++)
00829   {
00830     alpha=(text[i] & 0x000000ff) | ((text[map[1][i]]) & 0x0000ff00) |
00831       ((text[map[2][i]]) & 0x00ff0000) | ((text[map[3][i]]) & 0xff000000);
00832     key[i]=ByteSubTransform(alpha,SBox);
00833   }
00834   FinalizeRoundKey(key,aes_info->encipher_key+4*aes_info->rounds,ciphertext);
00835   /*
00836     Reset registers.
00837   */
00838   alpha=0;
00839   (void) ResetMagickMemory(key,0,sizeof(key));
00840   (void) ResetMagickMemory(text,0,sizeof(text));
00841 }
00842 
00843 /*
00844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00845 %                                                                             %
00846 %                                                                             %
00847 %                                                                             %
00848 %   S e t A E S K e y                                                         %
00849 %                                                                             %
00850 %                                                                             %
00851 %                                                                             %
00852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00853 %
00854 %  SetAESKey() sets the key for the AES cipher.  The key length is specified
00855 %  in bits.  Valid values are 128, 192, or 256 requiring a key buffer length
00856 %  in bytes of 16, 24, and 32 respectively.
00857 %
00858 %  The format of the SetAESKey method is:
00859 %
00860 %      SetAESKey(AESInfo *aes_info,const StringInfo *key)
00861 %
00862 %  A description of each parameter follows:
00863 %
00864 %    o aes_info: the cipher context.
00865 %
00866 %    o key: the key.
00867 %
00868 */
00869 
00870 static inline void InverseAddRoundKey(const unsigned int *alpha,
00871   unsigned int *beta)
00872 {
00873   register unsigned int
00874     i,
00875     j;
00876 
00877   for (i=0; i < 4; i++)
00878   {
00879     beta[i]=0;
00880     for (j=0; j < 4; j++)
00881       beta[i]|=(ByteMultiply(0xe,(alpha[i] >> (8*j)) & 0xff) ^
00882         ByteMultiply(0xb,(alpha[i] >> (8*((j+1) % 4))) & 0xff) ^
00883         ByteMultiply(0xd,(alpha[i] >> (8*((j+2) % 4))) & 0xff) ^
00884         ByteMultiply(0x9,(alpha[i] >> (8*((j+3) % 4))) & 0xff)) << (8*j);
00885   }
00886 }
00887 
00888 static inline unsigned int XTime(unsigned char alpha)
00889 {
00890   unsigned char
00891     beta;
00892 
00893   beta=(unsigned char) ((alpha & 0x80) != 0 ? 0x1b : 0);
00894   alpha<<=1;
00895   alpha^=beta;
00896   return(alpha);
00897 }
00898 
00899 static inline unsigned int RotateRight(const unsigned int x)
00900 {
00901   return((x >> 8) | ((x & 0xff) << 24));
00902 }
00903 
00904 static void SetAESKey(AESInfo *aes_info,const StringInfo *key)
00905 {
00906   long
00907     bytes,
00908     n;
00909 
00910   register long
00911     i;
00912 
00913   unsigned char
00914     *datum;
00915 
00916   unsigned int
00917     alpha,
00918     beta;
00919 
00920   /*
00921     Determine the number of rounds based on the number of bits in key.
00922   */
00923   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00924   assert(aes_info != (AESInfo *) NULL);
00925   assert(aes_info->signature == MagickSignature);
00926   assert(key != (StringInfo *) NULL);
00927   n=4;
00928   aes_info->rounds=10;
00929   if ((8*GetStringInfoLength(key)) >= 256)
00930     {
00931       n=8;
00932       aes_info->rounds=14;
00933     }
00934   else
00935     if ((8*GetStringInfoLength(key)) >= 192)
00936       {
00937         n=6;
00938         aes_info->rounds=12;
00939       }
00940   /*
00941     Generate crypt key.
00942   */
00943   datum=GetStringInfoDatum(aes_info->key);
00944   (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
00945   (void) CopyMagickMemory(datum,GetStringInfoDatum(key),MagickMin(
00946     GetStringInfoLength(key),GetStringInfoLength(aes_info->key)));
00947   for (i=0; i < n; i++)
00948     aes_info->encipher_key[i]=datum[4*i] | (datum[4*i+1] << 8) |
00949       (datum[4*i+2] << 16) | (datum[4*i+3] << 24);
00950   beta=1;
00951   bytes=(AESBlocksize/4)*(aes_info->rounds+1);
00952   for (i=n; i < bytes; i++)
00953   {
00954     alpha=aes_info->encipher_key[i-1];
00955     if ((i % n) == 0)
00956       {
00957         alpha=ByteSubTransform(RotateRight(alpha),SBox) ^ beta;
00958         beta=XTime((unsigned char) (beta & 0xff));
00959       }
00960     else
00961       if ((n > 6) && ((i % n) == 4))
00962         alpha=ByteSubTransform(alpha,SBox);
00963     aes_info->encipher_key[i]=aes_info->encipher_key[i-n] ^ alpha;
00964   }
00965   /*
00966     Generate deciper key (in reverse order).
00967   */
00968   for (i=0; i < 4; i++)
00969   {
00970     aes_info->decipher_key[i]=aes_info->encipher_key[i];
00971     aes_info->decipher_key[bytes-4+i]=aes_info->encipher_key[bytes-4+i];
00972   }
00973   for (i=4; i < (bytes-4); i+=4)
00974     InverseAddRoundKey(aes_info->encipher_key+i,aes_info->decipher_key+i);
00975   /*
00976     Reset registers.
00977   */
00978   datum=GetStringInfoDatum(aes_info->key);
00979   (void) ResetMagickMemory(datum,0,GetStringInfoLength(aes_info->key));
00980   alpha=0;
00981   beta=0;
00982 }
00983 #else
00984 
00985 /*
00986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00987 %                                                                             %
00988 %                                                                             %
00989 %                                                                             %
00990 +     D e c i p h e r I m a g e                                               %
00991 %                                                                             %
00992 %                                                                             %
00993 %                                                                             %
00994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00995 %
00996 %  DecipherImage() converts cipher pixels to plain pixels.
00997 %
00998 %  The format of the DecipherImage method is:
00999 %
01000 %      MagickBooleanType DecipherImage(Image *image,const char *passphrase,
01001 %        ExceptionInfo *exception)
01002 %
01003 %  A description of each parameter follows:
01004 %
01005 %    o image: the image.
01006 %
01007 %    o passphrase: decipher cipher pixels with this passphrase.
01008 %
01009 %    o exception: return any errors or warnings in this structure.
01010 %
01011 */
01012 MagickExport MagickBooleanType DecipherImage(Image *image,
01013   const char *passphrase,ExceptionInfo *exception)
01014 {
01015   assert(image != (Image *) NULL);
01016   assert(image->signature == MagickSignature);
01017   if (image->debug != MagickFalse)
01018     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01019   assert(exception != (ExceptionInfo *) NULL);
01020   assert(exception->signature == MagickSignature);
01021   (void) passphrase;
01022   ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
01023 }
01024 
01025 /*
01026 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01027 %                                                                             %
01028 %                                                                             %
01029 %                                                                             %
01030 +     E n c i p h e r I m a g e                                               %
01031 %                                                                             %
01032 %                                                                             %
01033 %                                                                             %
01034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01035 %
01036 %  EncipherImage() converts pixels to cipher-pixels.
01037 %
01038 %  The format of the EncipherImage method is:
01039 %
01040 %      MagickBooleanType EncipherImage(Image *image,const char *passphrase,
01041 %        ExceptionInfo *exception)
01042 %
01043 %  A description of each parameter follows:
01044 %
01045 %    o image: the image.
01046 %
01047 %    o passphrase: encipher pixels with this passphrase.
01048 %
01049 %    o exception: return any errors or warnings in this structure.
01050 %
01051 */
01052 MagickExport MagickBooleanType EncipherImage(Image *image,
01053   const char *passphrase,ExceptionInfo *exception)
01054 {
01055   assert(image != (Image *) NULL);
01056   assert(image->signature == MagickSignature);
01057   if (image->debug != MagickFalse)
01058     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01059   assert(exception != (ExceptionInfo *) NULL);
01060   assert(exception->signature == MagickSignature);
01061   (void) passphrase;
01062   ThrowBinaryException(ImageError,"CipherSupportNotEnabled",image->filename);
01063 }
01064 #endif

Generated on Thu Nov 20 21:54:43 2008 for MagickCore by  doxygen 1.5.7.1