You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

817 lines
29 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% SSSSS IIIII GGGG N N AAA TTTTT U U RRRR EEEEE %
% SS I G NN N A A T U U R R E %
% SSS I G GG N N N AAAAA T U U RRRR EEE %
% SS I G G N NN A A T U U R R E %
% SSSSS IIIII GGG N N A A T UUU R R EEEEE %
% %
% %
% MagickCore Methods to Compute a Message Digest for an Image %
% %
% Software Design %
% Cristy %
% December 1992 %
% %
% %
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/cache.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/property.h"
#include "MagickCore/image.h"
#include "MagickCore/memory_.h"
#include "MagickCore/memory-private.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/quantum.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/signature.h"
#include "MagickCore/signature-private.h"
#include "MagickCore/string_.h"
#include "MagickCore/timer-private.h"
/*
Define declarations.
*/
#define SignatureBlocksize 64
#define SignatureDigestsize 32
/*
Typedef declarations.
*/
struct _SignatureInfo
{
unsigned int
digestsize,
blocksize;
StringInfo
*digest,
*message;
unsigned int
*accumulator,
low_order,
high_order;
size_t
extent;
MagickBooleanType
lsb_first;
ssize_t
timestamp;
size_t
signature;
};
/*
Forward declarations.
*/
static void
TransformSignature(SignatureInfo *);
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ A c q u i r e S i g n a t u r e I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% AcquireSignatureInfo() allocate the SignatureInfo structure.
%
% The format of the AcquireSignatureInfo method is:
%
% SignatureInfo *AcquireSignatureInfo(void)
%
*/
MagickPrivate SignatureInfo *AcquireSignatureInfo(void)
{
SignatureInfo
*signature_info;
unsigned long
lsb_first;
signature_info=(SignatureInfo *) AcquireCriticalMemory(
sizeof(*signature_info));
(void) memset(signature_info,0,sizeof(*signature_info));
signature_info->digestsize=SignatureDigestsize;
signature_info->blocksize=SignatureBlocksize;
signature_info->digest=AcquireStringInfo(SignatureDigestsize);
signature_info->message=AcquireStringInfo(SignatureBlocksize);
signature_info->accumulator=(unsigned int *) AcquireQuantumMemory(
SignatureBlocksize,sizeof(*signature_info->accumulator));
if (signature_info->accumulator == (unsigned int *) NULL)
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
(void) memset(signature_info->accumulator,0,SignatureBlocksize*
sizeof(*signature_info->accumulator));
lsb_first=1;
signature_info->lsb_first=(int) (*(char *) &lsb_first) == 1 ? MagickTrue :
MagickFalse;
signature_info->timestamp=(ssize_t) GetMagickTime();
signature_info->signature=MagickCoreSignature;
InitializeSignature(signature_info);
return(signature_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D e s t r o y S i g n a t u r e I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroySignatureInfo() zeros memory associated with the SignatureInfo
% structure.
%
% The format of the DestroySignatureInfo method is:
%
% SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the cipher signature_info.
%
*/
MagickPrivate SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
if (signature_info->accumulator != (unsigned int *) NULL)
signature_info->accumulator=(unsigned int *) RelinquishMagickMemory(
signature_info->accumulator);
if (signature_info->message != (StringInfo *) NULL)
signature_info->message=DestroyStringInfo(signature_info->message);
if (signature_info->digest != (StringInfo *) NULL)
signature_info->digest=DestroyStringInfo(signature_info->digest);
signature_info->signature=(~MagickCoreSignature);
signature_info=(SignatureInfo *) RelinquishMagickMemory(signature_info);
return(signature_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ F i n a l i z e S i g n a t u r e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FinalizeSignature() finalizes the Signature message accumulator computation.
%
% The format of the FinalizeSignature method is:
%
% FinalizeSignature(SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the address of a structure of type SignatureInfo.
%
*/
MagickPrivate void FinalizeSignature(SignatureInfo *signature_info)
{
ssize_t
i;
unsigned char
*q;
unsigned int
*p;
size_t
extent;
unsigned char
*datum;
unsigned int
high_order,
low_order;
/*
Add padding and return the message accumulator.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
low_order=signature_info->low_order;
high_order=signature_info->high_order;
extent=((low_order >> 3) & 0x3f);
datum=GetStringInfoDatum(signature_info->message);
datum[extent++]=(unsigned char) 0x80;
if (extent <= (unsigned int) (GetStringInfoLength(signature_info->message)-8))
(void) memset(datum+extent,0,GetStringInfoLength(
signature_info->message)-8-extent);
else
{
(void) memset(datum+extent,0,GetStringInfoLength(
signature_info->message)-extent);
TransformSignature(signature_info);
(void) memset(datum,0,GetStringInfoLength(
signature_info->message)-8);
}
datum[56]=(unsigned char) (high_order >> 24);
datum[57]=(unsigned char) (high_order >> 16);
datum[58]=(unsigned char) (high_order >> 8);
datum[59]=(unsigned char) high_order;
datum[60]=(unsigned char) (low_order >> 24);
datum[61]=(unsigned char) (low_order >> 16);
datum[62]=(unsigned char) (low_order >> 8);
datum[63]=(unsigned char) low_order;
TransformSignature(signature_info);
p=signature_info->accumulator;
q=GetStringInfoDatum(signature_info->digest);
for (i=0; i < (SignatureDigestsize/4); i++)
{
*q++=(unsigned char) ((*p >> 24) & 0xff);
*q++=(unsigned char) ((*p >> 16) & 0xff);
*q++=(unsigned char) ((*p >> 8) & 0xff);
*q++=(unsigned char) (*p & 0xff);
p++;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t S i g n a t u r e B l o c k s i z e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetSignatureBlocksize() returns the Signature blocksize.
%
% The format of the GetSignatureBlocksize method is:
%
% unsigned int *GetSignatureBlocksize(const SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the signature info.
%
*/
MagickPrivate unsigned int GetSignatureBlocksize(
const SignatureInfo *signature_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
return(signature_info->blocksize);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t S i g n a t u r e D i g e s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetSignatureDigest() returns the signature digest.
%
% The format of the GetSignatureDigest method is:
%
% const StringInfo *GetSignatureDigest(const SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the signature info.
%
*/
MagickPrivate const StringInfo *GetSignatureDigest(
const SignatureInfo *signature_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
return(signature_info->digest);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t S i g n a t u r e D i g e s t s i z e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetSignatureDigestsize() returns the Signature digest size.
%
% The format of the GetSignatureDigestsize method is:
%
% unsigned int *GetSignatureDigestsize(const SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the signature info.
%
*/
MagickPrivate unsigned int GetSignatureDigestsize(
const SignatureInfo *signature_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
return(signature_info->digestsize);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ I n i t i a l i z e S i g n a t u r e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% InitializeSignature() initializes the Signature accumulator.
%
% The format of the DestroySignatureInfo method is:
%
% void InitializeSignatureInfo(SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the cipher signature_info.
%
*/
MagickPrivate void InitializeSignature(SignatureInfo *signature_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
signature_info->accumulator[0]=0x6a09e667U;
signature_info->accumulator[1]=0xbb67ae85U;
signature_info->accumulator[2]=0x3c6ef372U;
signature_info->accumulator[3]=0xa54ff53aU;
signature_info->accumulator[4]=0x510e527fU;
signature_info->accumulator[5]=0x9b05688cU;
signature_info->accumulator[6]=0x1f83d9abU;
signature_info->accumulator[7]=0x5be0cd19U;
signature_info->low_order=0;
signature_info->high_order=0;
signature_info->extent=0;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t S i g n a t u r e D i g e s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetSignatureDigest() set the signature digest.
%
% The format of the SetSignatureDigest method is:
%
% SetSignatureDigest(SignatureInfo *signature_info,
% const StringInfo *digest)
%
% A description of each parameter follows:
%
% o signature_info: the signature info.
%
% o digest: the digest.
%
*/
MagickPrivate void SetSignatureDigest(SignatureInfo *signature_info,
const StringInfo *digest)
{
/*
Set the signature accumulator.
*/
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
SetStringInfo(signature_info->digest,digest);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S i g n a t u r e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SignatureImage() computes a message digest from an image pixel stream with
% an implementation of the NIST SHA-256 Message Digest algorithm. This
% signature uniquely identifies the image and is convenient for determining
% if an image has been modified or whether two images are identical.
%
% The format of the SignatureImage method is:
%
% MagickBooleanType SignatureImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType SignatureImage(Image *image,
ExceptionInfo *exception)
{
CacheView
*image_view;
char
*hex_signature;
float
pixel;
const Quantum
*p;
SignatureInfo
*signature_info;
ssize_t
y;
StringInfo
*signature;
unsigned char
*pixels;
/*
Compute image digital signature.
*/
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
signature_info=AcquireSignatureInfo();
signature=AcquireStringInfo(GetPixelChannels(image)*image->columns*
sizeof(pixel));
image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
ssize_t
x;
unsigned char
*q;
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
SetStringInfoLength(signature,GetPixelChannels(image)*image->columns*
sizeof(pixel));
pixels=GetStringInfoDatum(signature);
q=pixels;
for (x=0; x < (ssize_t) image->columns; x++)
{
ssize_t
i;
if (GetPixelReadMask(image,p) <= (QuantumRange/2))
{
p+=GetPixelChannels(image);
continue;
}
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
ssize_t
j;
PixelChannel channel = GetPixelChannelChannel(image,i);
PixelTrait traits = GetPixelChannelTraits(image,channel);
if ((traits & UpdatePixelTrait) == 0)
continue;
pixel=(float) (QuantumScale*p[i]);
if (signature_info->lsb_first == MagickFalse)
for (j=(ssize_t) sizeof(pixel)-1; j >= 0; j--)
*q++=(unsigned char) ((unsigned char *) &pixel)[j];
else
for (j=0; j < (ssize_t) sizeof(pixel); j++)
*q++=(unsigned char) ((unsigned char *) &pixel)[j];
}
p+=GetPixelChannels(image);
}
SetStringInfoLength(signature,(size_t) (q-pixels));
UpdateSignature(signature_info,signature);
}
image_view=DestroyCacheView(image_view);
FinalizeSignature(signature_info);
hex_signature=StringInfoToHexString(GetSignatureDigest(signature_info));
(void) DeleteImageProperty(image,"signature");
(void) SetImageProperty(image,"signature",hex_signature,exception);
/*
Free resources.
*/
hex_signature=DestroyString(hex_signature);
signature=DestroyStringInfo(signature);
signature_info=DestroySignatureInfo(signature_info);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ T r a n s f o r m S i g n a t u r e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% TransformSignature() transforms the Signature message accumulator.
%
% The format of the TransformSignature method is:
%
% TransformSignature(SignatureInfo *signature_info)
%
% A description of each parameter follows:
%
% o signature_info: the address of a structure of type SignatureInfo.
%
*/
static void TransformSignature(SignatureInfo *signature_info)
{
#define Ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define RotateRight(x,n) (Trunc32(((x) >> n) | ((x) << (32-n))))
#define Sigma0(x) (RotateRight(x,7) ^ RotateRight(x,18) ^ Trunc32((x) >> 3))
#define Sigma1(x) (RotateRight(x,17) ^ RotateRight(x,19) ^ Trunc32((x) >> 10))
#define Suma0(x) (RotateRight(x,2) ^ RotateRight(x,13) ^ RotateRight(x,22))
#define Suma1(x) (RotateRight(x,6) ^ RotateRight(x,11) ^ RotateRight(x,25))
#define Trunc32(x) ((unsigned int) ((x) & 0xffffffffU))
ssize_t
i;
unsigned char
*p;
ssize_t
j;
static const unsigned int
K[64] =
{
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU,
0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U,
0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U,
0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U,
0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U,
0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U,
0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U,
0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU,
0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
}; /* 32-bit fractional part of the cube root of the first 64 primes */
unsigned int
A,
B,
C,
D,
E,
F,
G,
H,
shift,
T,
T1,
T2,
W[64];
shift=32;
p=GetStringInfoDatum(signature_info->message);
if (signature_info->lsb_first == MagickFalse)
{
DisableMSCWarning(4127)
if (sizeof(unsigned int) <= 4)
RestoreMSCWarning
for (i=0; i < 16; i++)
{
T=(*((unsigned int *) p));
p+=4;
W[i]=Trunc32(T);
}
else
for (i=0; i < 16; i+=2)
{
T=(*((unsigned int *) p));
p+=8;
W[i]=Trunc32(T >> shift);
W[i+1]=Trunc32(T);
}
}
else
DisableMSCWarning(4127)
if (sizeof(unsigned int) <= 4)
RestoreMSCWarning
for (i=0; i < 16; i++)
{
T=(*((unsigned int *) p));
p+=4;
W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
}
else
for (i=0; i < 16; i+=2)
{
T=(*((unsigned int *) p));
p+=8;
W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
T>>=shift;
W[i+1]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
}
/*
Copy accumulator to registers.
*/
A=signature_info->accumulator[0];
B=signature_info->accumulator[1];
C=signature_info->accumulator[2];
D=signature_info->accumulator[3];
E=signature_info->accumulator[4];
F=signature_info->accumulator[5];
G=signature_info->accumulator[6];
H=signature_info->accumulator[7];
for (i=16; i < 64; i++)
W[i]=Trunc32(Sigma1(W[i-2])+W[i-7]+Sigma0(W[i-15])+W[i-16]);
for (j=0; j < 64; j++)
{
T1=Trunc32(H+Suma1(E)+Ch(E,F,G)+K[j]+W[j]);
T2=Trunc32(Suma0(A)+Maj(A,B,C));
H=G;
G=F;
F=E;
E=Trunc32(D+T1);
D=C;
C=B;
B=A;
A=Trunc32(T1+T2);
}
/*
Add registers back to accumulator.
*/
signature_info->accumulator[0]=Trunc32(signature_info->accumulator[0]+A);
signature_info->accumulator[1]=Trunc32(signature_info->accumulator[1]+B);
signature_info->accumulator[2]=Trunc32(signature_info->accumulator[2]+C);
signature_info->accumulator[3]=Trunc32(signature_info->accumulator[3]+D);
signature_info->accumulator[4]=Trunc32(signature_info->accumulator[4]+E);
signature_info->accumulator[5]=Trunc32(signature_info->accumulator[5]+F);
signature_info->accumulator[6]=Trunc32(signature_info->accumulator[6]+G);
signature_info->accumulator[7]=Trunc32(signature_info->accumulator[7]+H);
/*
Reset working registers.
*/
A=0;
B=0;
C=0;
D=0;
E=0;
F=0;
G=0;
H=0;
T=0;
T1=0;
T2=0;
(void) ResetMagickMemory(W,0,sizeof(W));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ U p d a t e S i g n a t u r e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% UpdateSignature() updates the Signature message accumulator.
%
% The format of the UpdateSignature method is:
%
% UpdateSignature(SignatureInfo *signature_info,const StringInfo *message)
%
% A description of each parameter follows:
%
% o signature_info: the address of a structure of type SignatureInfo.
%
% o message: the message.
%
*/
MagickPrivate void UpdateSignature(SignatureInfo *signature_info,
const StringInfo *message)
{
size_t
i;
unsigned char
*p;
size_t
n;
unsigned int
length;
/*
Update the Signature accumulator.
*/
assert(signature_info != (SignatureInfo *) NULL);
assert(signature_info->signature == MagickCoreSignature);
n=GetStringInfoLength(message);
length=Trunc32((unsigned int) (signature_info->low_order+(n << 3)));
if (length < signature_info->low_order)
signature_info->high_order++;
signature_info->low_order=length;
signature_info->high_order+=(unsigned int) n >> 29;
p=GetStringInfoDatum(message);
if (signature_info->extent != 0)
{
i=GetStringInfoLength(signature_info->message)-signature_info->extent;
if (i > n)
i=n;
(void) memcpy(GetStringInfoDatum(signature_info->message)+
signature_info->extent,p,i);
n-=i;
p+=i;
signature_info->extent+=i;
if (signature_info->extent != GetStringInfoLength(signature_info->message))
return;
TransformSignature(signature_info);
}
while (n >= GetStringInfoLength(signature_info->message))
{
SetStringInfoDatum(signature_info->message,p);
p+=GetStringInfoLength(signature_info->message);
n-=GetStringInfoLength(signature_info->message);
TransformSignature(signature_info);
}
(void) memcpy(GetStringInfoDatum(signature_info->message),p,n);
signature_info->extent=n;
}