1 /* Copyright (c) 2002, 2004, 2006 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 Original Source from: http://www.faqs.org/rfcs/rfc3174.html
20 Copyright (C) The Internet Society (2001). All Rights Reserved.
22 This document and translations of it may be copied and furnished to
23 others, and derivative works that comment on or otherwise explain it
24 or assist in its implementation may be prepared, copied, published
25 and distributed, in whole or in part, without restriction of any
26 kind, provided that the above copyright notice and this paragraph are
27 included on all such copies and derivative works. However, this
28 document itself may not be modified in any way, such as by removing
29 the copyright notice or references to the Internet Society or other
30 Internet organizations, except as needed for the purpose of
31 developing Internet standards in which case the procedures for
32 copyrights defined in the Internet Standards process must be
33 followed, or as required to translate it into languages other than
36 The limited permissions granted above are perpetual and will not be
37 revoked by the Internet Society or its successors or assigns.
39 This document and the information contained herein is provided on an
40 "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
41 TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
42 BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
43 HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
44 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
47 Funding for the RFC Editor function is currently provided by the
51 This file implements the Secure Hashing Algorithm 1 as
52 defined in FIPS PUB 180-1 published April 17, 1995.
54 The SHA-1, produces a 160-bit message digest for a given data
55 stream. It should take about 2**n steps to find a message with the
56 same digest as a given message and 2**(n/2) to find any two
57 messages with the same digest, when n is the digest size in bits.
58 Therefore, this algorithm can serve as a means of providing a
59 "fingerprint" for a message.
62 SHA-1 is defined in terms of 32-bit "words". This code uses
63 <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned
64 integer types. If your C compiler does not support 32 bit unsigned
65 integers, this code is not appropriate.
68 SHA-1 is designed to work with messages less than 2^64 bits long.
69 Although SHA-1 allows a message digest to be generated for messages
70 of any number of bits less than 2^64, this implementation only
71 works with messages with a length that is a multiple of the size of
75 2002 by Peter Zaitsev to
76 - fit to new prototypes according to MySQL standard
78 - All checking is now done in debug only mode
82 #include "my_global.h"
87 Define the SHA1 circular left shift macro
90 #define SHA1CircularShift(bits,word) \
91 (((word) << (bits)) | ((word) >> (32-(bits))))
93 /* Local Function Prototyptes */
94 static void SHA1PadMessage(SHA1_CONTEXT
*);
95 static void SHA1ProcessMessageBlock(SHA1_CONTEXT
*);
99 Initialize SHA1Context
103 context [in/out] The context to reset.
106 This function will initialize the SHA1Context in preparation
107 for computing a new SHA1 message digest.
111 != SHA_SUCCESS sha Error Code.
115 const uint32 sha_const_key
[5]=
125 int mysql_sha1_reset(SHA1_CONTEXT
*context
)
133 context
->Message_Block_Index
= 0;
135 context
->Intermediate_Hash
[0] = sha_const_key
[0];
136 context
->Intermediate_Hash
[1] = sha_const_key
[1];
137 context
->Intermediate_Hash
[2] = sha_const_key
[2];
138 context
->Intermediate_Hash
[3] = sha_const_key
[3];
139 context
->Intermediate_Hash
[4] = sha_const_key
[4];
141 context
->Computed
= 0;
142 context
->Corrupted
= 0;
149 Return the 160-bit message digest into the array provided by the caller
153 context [in/out] The context to use to calculate the SHA-1 hash.
154 Message_Digest: [out] Where the digest is returned.
157 NOTE: The first octet of hash is stored in the 0th element,
158 the last octet of hash in the 19th element.
162 != SHA_SUCCESS sha Error Code.
165 int mysql_sha1_result(SHA1_CONTEXT
*context
,
166 uint8 Message_Digest
[SHA1_HASH_SIZE
])
171 if (!context
|| !Message_Digest
)
174 if (context
->Corrupted
)
175 return context
->Corrupted
;
178 if (!context
->Computed
)
180 SHA1PadMessage(context
);
181 /* message may be sensitive, clear it out */
182 bzero((char*) context
->Message_Block
,64);
183 context
->Length
= 0; /* and clear length */
184 context
->Computed
= 1;
187 for (i
= 0; i
< SHA1_HASH_SIZE
; i
++)
188 Message_Digest
[i
] = (int8
)((context
->Intermediate_Hash
[i
>>2] >> 8
189 * ( 3 - ( i
& 0x03 ) )));
195 Accepts an array of octets as the next portion of the message.
199 context [in/out] The SHA context to update
200 message_array An array of characters representing the next portion
202 length The length of the message in message_array
206 != SHA_SUCCESS sha Error Code.
209 int mysql_sha1_input(SHA1_CONTEXT
*context
, const uint8
*message_array
,
216 /* We assume client konows what it is doing in non-debug mode */
217 if (!context
|| !message_array
)
219 if (context
->Computed
)
220 return (context
->Corrupted
= SHA_STATE_ERROR
);
221 if (context
->Corrupted
)
222 return context
->Corrupted
;
227 context
->Message_Block
[context
->Message_Block_Index
++]=
228 (*message_array
& 0xFF);
229 context
->Length
+= 8; /* Length is in bits */
233 Then we're not debugging we assume we never will get message longer
236 if (context
->Length
== 0)
237 return (context
->Corrupted
= 1); /* Message is too long */
240 if (context
->Message_Block_Index
== 64)
242 SHA1ProcessMessageBlock(context
);
251 Process the next 512 bits of the message stored in the Message_Block array.
254 SHA1ProcessMessageBlock()
257 Many of the variable names in this code, especially the single
258 character names, were used because those were the names used in
262 /* Constants defined in SHA-1 */
263 static const uint32 K
[]=
272 static void SHA1ProcessMessageBlock(SHA1_CONTEXT
*context
)
274 int t
; /* Loop counter */
275 uint32 temp
; /* Temporary word value */
276 uint32 W
[80]; /* Word sequence */
277 uint32 A
, B
, C
, D
, E
; /* Word buffers */
281 Initialize the first 16 words in the array W
284 for (t
= 0; t
< 16; t
++)
287 W
[t
] = context
->Message_Block
[idx
] << 24;
288 W
[t
] |= context
->Message_Block
[idx
+ 1] << 16;
289 W
[t
] |= context
->Message_Block
[idx
+ 2] << 8;
290 W
[t
] |= context
->Message_Block
[idx
+ 3];
294 for (t
= 16; t
< 80; t
++)
296 W
[t
] = SHA1CircularShift(1,W
[t
-3] ^ W
[t
-8] ^ W
[t
-14] ^ W
[t
-16]);
299 A
= context
->Intermediate_Hash
[0];
300 B
= context
->Intermediate_Hash
[1];
301 C
= context
->Intermediate_Hash
[2];
302 D
= context
->Intermediate_Hash
[3];
303 E
= context
->Intermediate_Hash
[4];
305 for (t
= 0; t
< 20; t
++)
307 temp
= SHA1CircularShift(5,A
) + ((B
& C
) | ((~B
) & D
)) + E
+ W
[t
] + K
[0];
310 C
= SHA1CircularShift(30,B
);
315 for (t
= 20; t
< 40; t
++)
317 temp
= SHA1CircularShift(5,A
) + (B
^ C
^ D
) + E
+ W
[t
] + K
[1];
320 C
= SHA1CircularShift(30,B
);
325 for (t
= 40; t
< 60; t
++)
327 temp
= (SHA1CircularShift(5,A
) + ((B
& C
) | (B
& D
) | (C
& D
)) + E
+ W
[t
] +
331 C
= SHA1CircularShift(30,B
);
336 for (t
= 60; t
< 80; t
++)
338 temp
= SHA1CircularShift(5,A
) + (B
^ C
^ D
) + E
+ W
[t
] + K
[3];
341 C
= SHA1CircularShift(30,B
);
346 context
->Intermediate_Hash
[0] += A
;
347 context
->Intermediate_Hash
[1] += B
;
348 context
->Intermediate_Hash
[2] += C
;
349 context
->Intermediate_Hash
[3] += D
;
350 context
->Intermediate_Hash
[4] += E
;
352 context
->Message_Block_Index
= 0;
361 context: [in/out] The context to pad
364 According to the standard, the message must be padded to an even
365 512 bits. The first padding bit must be a '1'. The last 64 bits
366 represent the length of the original message. All bits in between
367 should be 0. This function will pad the message according to
368 those rules by filling the Message_Block array accordingly. It
369 will also call the ProcessMessageBlock function provided
370 appropriately. When it returns, it can be assumed that the message
371 digest has been computed.
375 static void SHA1PadMessage(SHA1_CONTEXT
*context
)
378 Check to see if the current message block is too small to hold
379 the initial padding bits and length. If so, we will pad the
380 block, process it, and then continue padding into a second
384 int i
=context
->Message_Block_Index
;
388 context
->Message_Block
[i
++] = 0x80;
389 bzero((char*) &context
->Message_Block
[i
],
390 sizeof(context
->Message_Block
[0])*(64-i
));
391 context
->Message_Block_Index
=64;
393 /* This function sets context->Message_Block_Index to zero */
394 SHA1ProcessMessageBlock(context
);
396 bzero((char*) &context
->Message_Block
[0],
397 sizeof(context
->Message_Block
[0])*56);
398 context
->Message_Block_Index
=56;
402 context
->Message_Block
[i
++] = 0x80;
403 bzero((char*) &context
->Message_Block
[i
],
404 sizeof(context
->Message_Block
[0])*(56-i
));
405 context
->Message_Block_Index
=56;
409 Store the message length as the last 8 octets
412 context
->Message_Block
[56] = (int8
) (context
->Length
>> 56);
413 context
->Message_Block
[57] = (int8
) (context
->Length
>> 48);
414 context
->Message_Block
[58] = (int8
) (context
->Length
>> 40);
415 context
->Message_Block
[59] = (int8
) (context
->Length
>> 32);
416 context
->Message_Block
[60] = (int8
) (context
->Length
>> 24);
417 context
->Message_Block
[61] = (int8
) (context
->Length
>> 16);
418 context
->Message_Block
[62] = (int8
) (context
->Length
>> 8);
419 context
->Message_Block
[63] = (int8
) (context
->Length
);
421 SHA1ProcessMessageBlock(context
);