blob: 6bb14cf0c7dd6e02ca5f11febaf56f263209064c [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% SSSSS IIIII GGGG N N AAA TTTTT U U RRRR EEEEE %
6% SS I G NN N A A T U U R R E %
7% SSS I G GG N N N AAAAA T U U RRRR EEE %
8% SS I G G N NN A A T U U R R E %
9% SSSSS IIIII GGG N N A A T UUU R R EEEEE %
10% %
11% %
12% MagickCore Methods to Compute a Message Digest for an Image %
13% %
14% Software Design %
15% John Cristy %
16% December 1992 %
17% %
18% %
cristy1454be72011-12-19 01:52:48 +000019% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000020% 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/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/cache.h"
44#include "MagickCore/exception.h"
45#include "MagickCore/exception-private.h"
46#include "MagickCore/property.h"
47#include "MagickCore/image.h"
48#include "MagickCore/memory_.h"
cristy7ef90722011-09-27 18:08:52 +000049#include "MagickCore/pixel-accessor.h"
cristy4c08aed2011-07-01 19:47:50 +000050#include "MagickCore/quantum.h"
51#include "MagickCore/quantum-private.h"
52#include "MagickCore/signature.h"
53#include "MagickCore/signature-private.h"
54#include "MagickCore/string_.h"
cristy3ed852e2009-09-05 21:47:34 +000055/*
56 Define declarations.
57*/
58#define SignatureBlocksize 64
59#define SignatureDigestsize 32
60
61/*
62 Typedef declarations.
63*/
64struct _SignatureInfo
cristy82b15832009-10-06 19:17:37 +000065{
cristy3ed852e2009-09-05 21:47:34 +000066 unsigned int
67 digestsize,
68 blocksize;
69
70 StringInfo
71 *digest,
72 *message;
73
74 unsigned int
75 *accumulator,
76 low_order,
77 high_order;
78
79 size_t
80 offset;
81
82 MagickBooleanType
83 lsb_first;
84
cristybb503372010-05-27 20:51:26 +000085 ssize_t
cristy3ed852e2009-09-05 21:47:34 +000086 timestamp;
87
cristybb503372010-05-27 20:51:26 +000088 size_t
cristy3ed852e2009-09-05 21:47:34 +000089 signature;
90};
91
92/*
93 Forward declarations.
94*/
95static void
96 TransformSignature(SignatureInfo *);
97
98/*
99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100% %
101% %
102% %
103+ A c q u i r e S i g n a t u r e I n f o %
104% %
105% %
106% %
107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108%
109% AcquireSignatureInfo() allocate the SignatureInfo structure.
110%
111% The format of the AcquireSignatureInfo method is:
112%
113% SignatureInfo *AcquireSignatureInfo(void)
114%
115*/
cristy7832dc22011-09-05 01:21:53 +0000116MagickPrivate SignatureInfo *AcquireSignatureInfo(void)
cristy3ed852e2009-09-05 21:47:34 +0000117{
118 SignatureInfo
119 *signature_info;
120
121 unsigned int
122 lsb_first;
123
cristy73bd4a52010-10-05 11:24:23 +0000124 signature_info=(SignatureInfo *) AcquireMagickMemory(sizeof(*signature_info));
cristy3ed852e2009-09-05 21:47:34 +0000125 if (signature_info == (SignatureInfo *) NULL)
126 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
127 (void) ResetMagickMemory(signature_info,0,sizeof(*signature_info));
128 signature_info->digestsize=SignatureDigestsize;
129 signature_info->blocksize=SignatureBlocksize;
130 signature_info->digest=AcquireStringInfo(SignatureDigestsize);
131 signature_info->message=AcquireStringInfo(SignatureBlocksize);
132 signature_info->accumulator=(unsigned int *) AcquireQuantumMemory(
133 SignatureBlocksize,sizeof(*signature_info->accumulator));
134 if (signature_info->accumulator == (unsigned int *) NULL)
135 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
136 lsb_first=1;
137 signature_info->lsb_first=(int) (*(char *) &lsb_first) == 1 ? MagickTrue :
138 MagickFalse;
cristybb503372010-05-27 20:51:26 +0000139 signature_info->timestamp=(ssize_t) time(0);
cristy3ed852e2009-09-05 21:47:34 +0000140 signature_info->signature=MagickSignature;
141 InitializeSignature(signature_info);
142 return(signature_info);
143}
144
145/*
146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147% %
148% %
149% %
150+ D e s t r o y S i g n a t u r e I n f o %
151% %
152% %
153% %
154%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155%
156% DestroySignatureInfo() zeros memory associated with the SignatureInfo
157% structure.
158%
159% The format of the DestroySignatureInfo method is:
160%
161% SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
162%
163% A description of each parameter follows:
164%
165% o signature_info: the cipher signature_info.
166%
167*/
cristy7832dc22011-09-05 01:21:53 +0000168MagickPrivate SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
cristy3ed852e2009-09-05 21:47:34 +0000169{
170 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
171 assert(signature_info != (SignatureInfo *) NULL);
172 assert(signature_info->signature == MagickSignature);
173 if (signature_info->accumulator != (unsigned int *) NULL)
174 signature_info->accumulator=(unsigned int *) RelinquishMagickMemory(
175 signature_info->accumulator);
176 if (signature_info->message != (StringInfo *) NULL)
177 signature_info->message=DestroyStringInfo(signature_info->message);
178 if (signature_info->digest != (StringInfo *) NULL)
179 signature_info->digest=DestroyStringInfo(signature_info->digest);
180 signature_info->signature=(~MagickSignature);
181 signature_info=(SignatureInfo *) RelinquishMagickMemory(signature_info);
182 return(signature_info);
183}
184
185/*
186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187% %
188% %
189% %
190+ F i n a l i z e S i g n a t u r e %
191% %
192% %
193% %
194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195%
196% FinalizeSignature() finalizes the Signature message accumulator computation.
197%
198% The format of the FinalizeSignature method is:
199%
200% FinalizeSignature(SignatureInfo *signature_info)
201%
202% A description of each parameter follows:
203%
204% o signature_info: the address of a structure of type SignatureInfo.
205%
206*/
cristy7832dc22011-09-05 01:21:53 +0000207MagickPrivate void FinalizeSignature(SignatureInfo *signature_info)
cristy3ed852e2009-09-05 21:47:34 +0000208{
cristybb503372010-05-27 20:51:26 +0000209 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000210 i;
211
212 register unsigned char
213 *q;
214
215 register unsigned int
216 *p;
217
218 unsigned char
219 *datum;
220
221 unsigned int
222 count,
223 high_order,
224 low_order;
225
226 /*
227 Add padding and return the message accumulator.
228 */
229 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
230 assert(signature_info != (SignatureInfo *) NULL);
231 assert(signature_info->signature == MagickSignature);
232 low_order=signature_info->low_order;
233 high_order=signature_info->high_order;
234 count=((low_order >> 3) & 0x3f);
235 datum=GetStringInfoDatum(signature_info->message);
236 datum[count++]=(unsigned char) 0x80;
237 if (count <= (unsigned int) (GetStringInfoLength(signature_info->message)-8))
238 (void) ResetMagickMemory(datum+count,0,GetStringInfoLength(
239 signature_info->message)-8-count);
240 else
241 {
242 (void) ResetMagickMemory(datum+count,0,GetStringInfoLength(
243 signature_info->message)-count);
244 TransformSignature(signature_info);
245 (void) ResetMagickMemory(datum,0,GetStringInfoLength(
246 signature_info->message)-8);
247 }
248 datum[56]=(unsigned char) (high_order >> 24);
249 datum[57]=(unsigned char) (high_order >> 16);
250 datum[58]=(unsigned char) (high_order >> 8);
251 datum[59]=(unsigned char) high_order;
252 datum[60]=(unsigned char) (low_order >> 24);
253 datum[61]=(unsigned char) (low_order >> 16);
254 datum[62]=(unsigned char) (low_order >> 8);
255 datum[63]=(unsigned char) low_order;
256 TransformSignature(signature_info);
257 p=signature_info->accumulator;
258 q=GetStringInfoDatum(signature_info->digest);
259 for (i=0; i < (SignatureDigestsize/4); i++)
260 {
261 *q++=(unsigned char) ((*p >> 24) & 0xff);
262 *q++=(unsigned char) ((*p >> 16) & 0xff);
263 *q++=(unsigned char) ((*p >> 8) & 0xff);
264 *q++=(unsigned char) (*p & 0xff);
265 p++;
266 }
267 /*
268 Reset working registers.
269 */
270 count=0;
271 high_order=0;
272 low_order=0;
273}
274
275/*
276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277% %
278% %
279% %
280+ G e t S i g n a t u r e B l o c k s i z e %
281% %
282% %
283% %
284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285%
286% GetSignatureBlocksize() returns the Signature blocksize.
287%
288% The format of the GetSignatureBlocksize method is:
289%
290% unsigned int *GetSignatureBlocksize(const SignatureInfo *signature_info)
291%
292% A description of each parameter follows:
293%
294% o signature_info: the signature info.
295%
296*/
cristy7832dc22011-09-05 01:21:53 +0000297MagickPrivate unsigned int GetSignatureBlocksize(
cristy3ed852e2009-09-05 21:47:34 +0000298 const SignatureInfo *signature_info)
299{
300 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
301 assert(signature_info != (SignatureInfo *) NULL);
302 assert(signature_info->signature == MagickSignature);
303 return(signature_info->blocksize);
304}
305
306/*
307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308% %
309% %
310% %
311+ G e t S i g n a t u r e D i g e s t %
312% %
313% %
314% %
315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316%
317% GetSignatureDigest() returns the signature digest.
318%
319% The format of the GetSignatureDigest method is:
320%
321% const StringInfo *GetSignatureDigest(const SignatureInfo *signature_info)
322%
323% A description of each parameter follows:
324%
325% o signature_info: the signature info.
326%
327*/
cristy7832dc22011-09-05 01:21:53 +0000328MagickPrivate const StringInfo *GetSignatureDigest(
cristy3ed852e2009-09-05 21:47:34 +0000329 const SignatureInfo *signature_info)
330{
331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
332 assert(signature_info != (SignatureInfo *) NULL);
333 assert(signature_info->signature == MagickSignature);
334 return(signature_info->digest);
335}
336
337/*
338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339% %
340% %
341% %
342+ G e t S i g n a t u r e D i g e s t s i z e %
343% %
344% %
345% %
346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347%
348% GetSignatureDigestsize() returns the Signature digest size.
349%
350% The format of the GetSignatureDigestsize method is:
351%
352% unsigned int *GetSignatureDigestsize(const SignatureInfo *signature_info)
353%
354% A description of each parameter follows:
355%
356% o signature_info: the signature info.
357%
358*/
cristy7832dc22011-09-05 01:21:53 +0000359MagickPrivate unsigned int GetSignatureDigestsize(
cristy3ed852e2009-09-05 21:47:34 +0000360 const SignatureInfo *signature_info)
361{
362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
363 assert(signature_info != (SignatureInfo *) NULL);
364 assert(signature_info->signature == MagickSignature);
365 return(signature_info->digestsize);
366}
367
368/*
369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370% %
371% %
372% %
373+ I n i t i a l i z e S i g n a t u r e %
374% %
375% %
376% %
377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378%
glennrpbca49a22011-07-01 12:18:22 +0000379% InitializeSignature() initializes the Signature accumulator.
cristy3ed852e2009-09-05 21:47:34 +0000380%
381% The format of the DestroySignatureInfo method is:
382%
383% void InitializeSignatureInfo(SignatureInfo *signature_info)
384%
385% A description of each parameter follows:
386%
387% o signature_info: the cipher signature_info.
388%
389*/
cristy7832dc22011-09-05 01:21:53 +0000390MagickPrivate void InitializeSignature(SignatureInfo *signature_info)
cristy3ed852e2009-09-05 21:47:34 +0000391{
392 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
393 assert(signature_info != (SignatureInfo *) NULL);
394 assert(signature_info->signature == MagickSignature);
395 signature_info->accumulator[0]=0x6a09e667U;
396 signature_info->accumulator[1]=0xbb67ae85U;
397 signature_info->accumulator[2]=0x3c6ef372U;
398 signature_info->accumulator[3]=0xa54ff53aU;
399 signature_info->accumulator[4]=0x510e527fU;
400 signature_info->accumulator[5]=0x9b05688cU;
401 signature_info->accumulator[6]=0x1f83d9abU;
402 signature_info->accumulator[7]=0x5be0cd19U;
403 signature_info->low_order=0;
404 signature_info->high_order=0;
405 signature_info->offset=0;
406}
407
408/*
409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
410% %
411% %
412% %
413+ S e t S i g n a t u r e D i g e s t %
414% %
415% %
416% %
417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418%
419% SetSignatureDigest() set the signature digest.
420%
421% The format of the SetSignatureDigest method is:
422%
423% SetSignatureDigest(SignatureInfo *signature_info,
424% const StringInfo *digest)
425%
426% A description of each parameter follows:
427%
428% o signature_info: the signature info.
429%
430% o digest: the digest.
431%
432*/
cristy7832dc22011-09-05 01:21:53 +0000433MagickPrivate void SetSignatureDigest(SignatureInfo *signature_info,
cristy3ed852e2009-09-05 21:47:34 +0000434 const StringInfo *digest)
435{
436 /*
437 Set the signature accumulator.
438 */
439 assert(signature_info != (SignatureInfo *) NULL);
440 assert(signature_info->signature == MagickSignature);
441 SetStringInfo(signature_info->digest,digest);
442}
443
444/*
445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446% %
447% %
448% %
449% S i g n a t u r e I m a g e %
450% %
451% %
452% %
453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454%
455% SignatureImage() computes a message digest from an image pixel stream with
456% an implementation of the NIST SHA-256 Message Digest algorithm. This
457% signature uniquely identifies the image and is convenient for determining
458% if an image has been modified or whether two images are identical.
459%
460% The format of the SignatureImage method is:
461%
cristy018f07f2011-09-04 21:15:19 +0000462% MagickBooleanType SignatureImage(Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000463%
464% A description of each parameter follows:
465%
466% o image: the image.
467%
cristy018f07f2011-09-04 21:15:19 +0000468% o exception: return any errors or warnings in this structure.
469%
cristy3ed852e2009-09-05 21:47:34 +0000470*/
cristy018f07f2011-09-04 21:15:19 +0000471MagickExport MagickBooleanType SignatureImage(Image *image,
472 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000473{
cristyc4c8d132010-01-07 01:58:38 +0000474 CacheView
475 *image_view;
476
cristy3ed852e2009-09-05 21:47:34 +0000477 char
478 *hex_signature;
479
cristy11165b72011-09-28 17:26:49 +0000480 double
481 pixel;
cristy3ed852e2009-09-05 21:47:34 +0000482
cristy4c08aed2011-07-01 19:47:50 +0000483 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000484 *p;
485
486 SignatureInfo
487 *signature_info;
488
cristy9d314ff2011-03-09 01:30:28 +0000489 ssize_t
490 y;
491
cristy3ed852e2009-09-05 21:47:34 +0000492 StringInfo
493 *signature;
494
495 unsigned char
496 *pixels;
497
cristy3ed852e2009-09-05 21:47:34 +0000498 /*
499 Compute image digital signature.
500 */
501 assert(image != (Image *) NULL);
502 assert(image->signature == MagickSignature);
503 if (image->debug != MagickFalse)
504 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000505 signature_info=AcquireSignatureInfo();
cristy34be0652011-09-28 00:00:36 +0000506 signature=AcquireStringInfo(image->columns*GetPixelChannels(image)*
cristy11165b72011-09-28 17:26:49 +0000507 sizeof(pixel));
cristy7ef90722011-09-27 18:08:52 +0000508 pixels=GetStringInfoDatum(signature);
cristydb070952012-04-20 14:33:00 +0000509 image_view=AcquireVirtualCacheView(image,exception);
cristybb503372010-05-27 20:51:26 +0000510 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000511 {
cristy7ef90722011-09-27 18:08:52 +0000512 register ssize_t
513 x;
514
cristy34be0652011-09-28 00:00:36 +0000515 register unsigned char
516 *q;
517
cristy3ed852e2009-09-05 21:47:34 +0000518 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000519 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000520 break;
cristy34be0652011-09-28 00:00:36 +0000521 q=pixels;
cristy7ef90722011-09-27 18:08:52 +0000522 for (x=0; x < (ssize_t) image->columns; x++)
523 {
524 register ssize_t
525 i;
526
cristy10a6c612012-01-29 21:41:05 +0000527 if (GetPixelMask(image,p) != 0)
528 {
529 p+=GetPixelChannels(image);
530 continue;
531 }
cristy7ef90722011-09-27 18:08:52 +0000532 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
533 {
cristyabace412011-12-11 15:56:53 +0000534 PixelChannel
535 channel;
536
cristy7ef90722011-09-27 18:08:52 +0000537 PixelTrait
538 traits;
539
540 register ssize_t
541 j;
542
cristycf1296e2012-08-26 23:40:49 +0000543 channel=GetPixelChannelChannel(image,i);
544 traits=GetPixelChannelTraits(image,channel);
cristy7ef90722011-09-27 18:08:52 +0000545 if (traits == UndefinedPixelTrait)
546 continue;
cristy11165b72011-09-28 17:26:49 +0000547 pixel=QuantumScale*p[i];
548 for (j=0; j < (ssize_t) sizeof(pixel); j++)
549 *q++=(unsigned char) (&pixel)[j];
cristy7ef90722011-09-27 18:08:52 +0000550 }
551 p+=GetPixelChannels(image);
552 }
cristy34be0652011-09-28 00:00:36 +0000553 SetStringInfoLength(signature,(size_t) (q-pixels));
554 UpdateSignature(signature_info,signature);
cristy3ed852e2009-09-05 21:47:34 +0000555 }
556 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +0000557 FinalizeSignature(signature_info);
558 hex_signature=StringInfoToHexString(GetSignatureDigest(signature_info));
559 (void) DeleteImageProperty(image,"signature");
cristyd15e6592011-10-15 00:13:06 +0000560 (void) SetImageProperty(image,"signature",hex_signature,exception);
cristy3ed852e2009-09-05 21:47:34 +0000561 /*
562 Free resources.
563 */
564 hex_signature=DestroyString(hex_signature);
565 signature=DestroyStringInfo(signature);
566 signature_info=DestroySignatureInfo(signature_info);
567 return(MagickTrue);
568}
569
570/*
571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572% %
573% %
574% %
575+ T r a n s f o r m S i g n a t u r e %
576% %
577% %
578% %
579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580%
581% TransformSignature() transforms the Signature message accumulator.
582%
583% The format of the TransformSignature method is:
584%
585% TransformSignature(SignatureInfo *signature_info)
586%
587% A description of each parameter follows:
588%
589% o signature_info: the address of a structure of type SignatureInfo.
590%
591*/
592
593static inline unsigned int Ch(unsigned int x,unsigned int y,unsigned int z)
594{
595 return((x & y) ^ (~x & z));
596}
597
598static inline unsigned int Maj(unsigned int x,unsigned int y,unsigned int z)
599{
600 return((x & y) ^ (x & z) ^ (y & z));
601}
602
603static inline unsigned int Trunc32(unsigned int x)
604{
605 return((unsigned int) (x & 0xffffffffU));
606}
607
608static unsigned int RotateRight(unsigned int x,unsigned int n)
609{
610 return(Trunc32((x >> n) | (x << (32-n))));
611}
612
613static void TransformSignature(SignatureInfo *signature_info)
614{
615#define Sigma0(x) (RotateRight(x,7) ^ RotateRight(x,18) ^ Trunc32((x) >> 3))
616#define Sigma1(x) (RotateRight(x,17) ^ RotateRight(x,19) ^ Trunc32((x) >> 10))
617#define Suma0(x) (RotateRight(x,2) ^ RotateRight(x,13) ^ RotateRight(x,22))
618#define Suma1(x) (RotateRight(x,6) ^ RotateRight(x,11) ^ RotateRight(x,25))
619
cristybb503372010-05-27 20:51:26 +0000620 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000621 i;
622
623 register unsigned char
624 *p;
625
cristy9d314ff2011-03-09 01:30:28 +0000626 ssize_t
627 j;
628
cristy3ed852e2009-09-05 21:47:34 +0000629 static unsigned int
630 K[64] =
631 {
632 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU,
633 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U,
634 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U,
635 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
636 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U,
637 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U,
638 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
639 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
640 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U,
641 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U,
642 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU,
643 0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
644 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
645 }; /* 32-bit fractional part of the cube root of the first 64 primes */
646
647 unsigned int
648 A,
649 B,
650 C,
651 D,
652 E,
653 F,
654 G,
655 H,
656 shift,
657 T,
658 T1,
659 T2,
660 W[64];
661
662 shift=32;
663 p=GetStringInfoDatum(signature_info->message);
664 if (signature_info->lsb_first == MagickFalse)
665 {
666 if (sizeof(unsigned int) <= 4)
667 for (i=0; i < 16; i++)
668 {
669 T=(*((unsigned int *) p));
670 p+=4;
671 W[i]=Trunc32(T);
672 }
673 else
674 for (i=0; i < 16; i+=2)
675 {
676 T=(*((unsigned int *) p));
677 p+=8;
678 W[i]=Trunc32(T >> shift);
679 W[i+1]=Trunc32(T);
680 }
681 }
682 else
683 if (sizeof(unsigned int) <= 4)
684 for (i=0; i < 16; i++)
685 {
686 T=(*((unsigned int *) p));
687 p+=4;
688 W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
689 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
690 }
691 else
692 for (i=0; i < 16; i+=2)
693 {
694 T=(*((unsigned int *) p));
695 p+=8;
696 W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
697 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
698 T>>=shift;
699 W[i+1]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
700 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
701 }
702 /*
703 Copy accumulator to registers.
704 */
705 A=signature_info->accumulator[0];
706 B=signature_info->accumulator[1];
707 C=signature_info->accumulator[2];
708 D=signature_info->accumulator[3];
709 E=signature_info->accumulator[4];
710 F=signature_info->accumulator[5];
711 G=signature_info->accumulator[6];
712 H=signature_info->accumulator[7];
713 for (i=16; i < 64; i++)
714 W[i]=Trunc32(Sigma1(W[i-2])+W[i-7]+Sigma0(W[i-15])+W[i-16]);
715 for (j=0; j < 64; j++)
716 {
717 T1=Trunc32(H+Suma1(E)+Ch(E,F,G)+K[j]+W[j]);
718 T2=Trunc32(Suma0(A)+Maj(A,B,C));
719 H=G;
720 G=F;
721 F=E;
722 E=Trunc32(D+T1);
723 D=C;
724 C=B;
725 B=A;
726 A=Trunc32(T1+T2);
727 }
728 /*
729 Add registers back to accumulator.
730 */
731 signature_info->accumulator[0]=Trunc32(signature_info->accumulator[0]+A);
732 signature_info->accumulator[1]=Trunc32(signature_info->accumulator[1]+B);
733 signature_info->accumulator[2]=Trunc32(signature_info->accumulator[2]+C);
734 signature_info->accumulator[3]=Trunc32(signature_info->accumulator[3]+D);
735 signature_info->accumulator[4]=Trunc32(signature_info->accumulator[4]+E);
736 signature_info->accumulator[5]=Trunc32(signature_info->accumulator[5]+F);
737 signature_info->accumulator[6]=Trunc32(signature_info->accumulator[6]+G);
738 signature_info->accumulator[7]=Trunc32(signature_info->accumulator[7]+H);
739 /*
740 Reset working registers.
741 */
742 A=0;
743 B=0;
744 C=0;
745 D=0;
746 E=0;
747 F=0;
748 G=0;
749 H=0;
750 T=0;
751 T1=0;
752 T2=0;
753 (void) ResetMagickMemory(W,0,sizeof(W));
754}
755
756/*
757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758% %
759% %
760% %
761+ U p d a t e S i g n a t u r e %
762% %
763% %
764% %
765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766%
767% UpdateSignature() updates the Signature message accumulator.
768%
769% The format of the UpdateSignature method is:
770%
771% UpdateSignature(SignatureInfo *signature_info,const StringInfo *message)
772%
773% A description of each parameter follows:
774%
775% o signature_info: the address of a structure of type SignatureInfo.
776%
777% o message: the message.
778%
779*/
cristy7832dc22011-09-05 01:21:53 +0000780MagickPrivate void UpdateSignature(SignatureInfo *signature_info,
cristy3ed852e2009-09-05 21:47:34 +0000781 const StringInfo *message)
782{
783 register size_t
784 i;
785
786 register unsigned char
787 *p;
788
789 size_t
790 n;
791
792 unsigned int
793 length;
794
795 /*
796 Update the Signature accumulator.
797 */
798 assert(signature_info != (SignatureInfo *) NULL);
799 assert(signature_info->signature == MagickSignature);
800 n=GetStringInfoLength(message);
801 length=Trunc32((unsigned int) (signature_info->low_order+(n << 3)));
802 if (length < signature_info->low_order)
803 signature_info->high_order++;
804 signature_info->low_order=length;
805 signature_info->high_order+=(unsigned int) (n >> 29);
806 p=GetStringInfoDatum(message);
807 if (signature_info->offset != 0)
808 {
809 i=GetStringInfoLength(signature_info->message)-signature_info->offset;
810 if (i > n)
811 i=n;
812 (void) CopyMagickMemory(GetStringInfoDatum(signature_info->message)+
813 signature_info->offset,p,i);
814 n-=i;
815 p+=i;
816 signature_info->offset+=i;
817 if (signature_info->offset !=
818 GetStringInfoLength(signature_info->message))
819 return;
820 TransformSignature(signature_info);
821 }
822 while (n >= GetStringInfoLength(signature_info->message))
823 {
824 SetStringInfoDatum(signature_info->message,p);
825 p+=GetStringInfoLength(signature_info->message);
826 n-=GetStringInfoLength(signature_info->message);
827 TransformSignature(signature_info);
828 }
829 (void) CopyMagickMemory(GetStringInfoDatum(signature_info->message),p,n);
830 signature_info->offset=n;
831 /*
832 Reset working registers.
833 */
834 i=0;
835 n=0;
836 length=0;
837}