CUBRID Engine  latest
sha1.c
Go to the documentation of this file.
1 /*
2  * sha1.c
3  *
4  * Copyright (C) 1998
5  * Paul E. Jones <paulej@arid.us>
6  * All Rights Reserved
7  *
8  *****************************************************************************
9  * $Id: sha1.c,v 1.2 2004/03/27 18:00:33 paulej Exp $
10  *****************************************************************************
11  *
12  * Description:
13  * This file implements the Secure Hashing Standard as defined
14  * in FIPS PUB 180-1 published April 17, 1995.
15  *
16  * The Secure Hashing Standard, which uses the Secure Hashing
17  * Algorithm (SHA), produces a 160-bit message digest for a
18  * given data stream. In theory, it is highly improbable that
19  * two messages will produce the same message digest. Therefore,
20  * this algorithm can serve as a means of providing a "fingerprint"
21  * for a message.
22  *
23  * Portability Issues:
24  * SHA-1 is defined in terms of 32-bit "words". This code was
25  * written with the expectation that the processor has at least
26  * a 32-bit machine word size. If the machine word size is larger,
27  * the code should still function properly. One caveat to that
28  * is that the input functions taking characters and character
29  * arrays assume that only 8 bits of information are stored in each
30  * character.
31  *
32  * Caveats:
33  * SHA-1 is designed to work with messages less than 2^64 bits
34  * long. Although SHA-1 allows a message digest to be generated for
35  * messages of any number of bits less than 2^64, this
36  * implementation only works with messages with a length that is a
37  * multiple of the size of an 8-bit character.
38  *
39  */
40 
41 #include "sha1.h"
42 #include "error_manager.h"
43 
44 #include <assert.h>
45 
46 /*
47  * Define the circular shift macro
48  */
49 #define SHA1CircularShift(bits,word) \
50  ((((word) << (bits)) & 0xFFFFFFFF) | \
51  ((word) >> (32-(bits))))
52 
53 /* Function prototypes */
56 
57 /*
58  * SHA1Reset
59  *
60  * Description:
61  * This function will initialize the SHA1Context in preparation
62  * for computing a new message digest.
63  *
64  * Parameters:
65  * context: [in/out]
66  * The context to reset.
67  *
68  * Returns:
69  * Nothing.
70  *
71  * Comments:
72  *
73  */
74 void
76 {
77  context->Length_Low = 0;
78  context->Length_High = 0;
79  context->Message_Block_Index = 0;
80 
81  context->Message_Digest[0] = 0x67452301;
82  context->Message_Digest[1] = 0xEFCDAB89;
83  context->Message_Digest[2] = 0x98BADCFE;
84  context->Message_Digest[3] = 0x10325476;
85  context->Message_Digest[4] = 0xC3D2E1F0;
86 
87  context->Computed = 0;
88  context->Corrupted = 0;
89 }
90 
91 /*
92  * SHA1Result
93  *
94  * Description:
95  * This function will return the 160-bit message digest into the
96  * Message_Digest array within the SHA1Context provided
97  *
98  * Parameters:
99  * context: [in/out]
100  * The context to use to calculate the SHA-1 hash.
101  *
102  * Returns:
103  * 1 if successful, 0 if it failed.
104  *
105  * Comments:
106  *
107  */
108 int
110 {
111 
112  if (context->Corrupted)
113  {
114  return 0;
115  }
116 
117  if (!context->Computed)
118  {
119  SHA1PadMessage (context);
120  context->Computed = 1;
121  }
122 
123  return 1;
124 }
125 
126 /*
127  * SHA1Input
128  *
129  * Description:
130  * This function accepts an array of octets as the next portion of
131  * the message.
132  *
133  * Parameters:
134  * context: [in/out]
135  * The SHA-1 context to update
136  * message_array: [in]
137  * An array of characters representing the next portion of the
138  * message.
139  * length: [in]
140  * The length of the message in message_array
141  *
142  * Returns:
143  * Nothing.
144  *
145  * Comments:
146  *
147  */
148 void
149 SHA1Input (SHA1Context * context, const unsigned char *message_array, size_t length)
150 {
151  if (length == 0)
152  {
153  return;
154  }
155 
156  if (context->Computed || context->Corrupted)
157  {
158  context->Corrupted = 1;
159  return;
160  }
161 
162  while (length-- > 0 && !context->Corrupted)
163  {
164  context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
165 
166  context->Length_Low += 8;
167  /* Force it to 32 bits */
168  context->Length_Low &= 0xFFFFFFFF;
169  if (context->Length_Low == 0)
170  {
171  context->Length_High++;
172  /* Force it to 32 bits */
173  context->Length_High &= 0xFFFFFFFF;
174  if (context->Length_High == 0)
175  {
176  /* Message is too long */
177  context->Corrupted = 1;
178  }
179  }
180 
181  if (context->Message_Block_Index == 64)
182  {
183  SHA1ProcessMessageBlock (context);
184  }
185 
186  message_array++;
187  }
188 }
189 
190 /*
191  * SHA1ProcessMessageBlock
192  *
193  * Description:
194  * This function will process the next 512 bits of the message
195  * stored in the Message_Block array.
196  *
197  * Parameters:
198  * None.
199  *
200  * Returns:
201  * Nothing.
202  *
203  * Comments:
204  * Many of the variable names in the SHAContext, especially the
205  * single character names, were used because those were the names
206  * used in the publication.
207  *
208  *
209  */
210 void
212 {
213  const unsigned K[] = /* Constants defined in SHA-1 */
214  {
215  0x5A827999,
216  0x6ED9EBA1,
217  0x8F1BBCDC,
218  0xCA62C1D6
219  };
220  int t; /* Loop counter */
221  unsigned temp; /* Temporary word value */
222  unsigned W[80]; /* Word sequence */
223  unsigned A, B, C, D, E; /* Word buffers */
224 
225  /*
226  * Initialize the first 16 words in the array W
227  */
228  for (t = 0; t < 16; t++)
229  {
230  W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
231  W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
232  W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
233  W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
234  }
235 
236  for (t = 16; t < 80; t++)
237  {
238  W[t] = SHA1CircularShift (1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
239  }
240 
241  A = context->Message_Digest[0];
242  B = context->Message_Digest[1];
243  C = context->Message_Digest[2];
244  D = context->Message_Digest[3];
245  E = context->Message_Digest[4];
246 
247  for (t = 0; t < 20; t++)
248  {
249  temp = SHA1CircularShift (5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
250  temp &= 0xFFFFFFFF;
251  E = D;
252  D = C;
253  C = SHA1CircularShift (30, B);
254  B = A;
255  A = temp;
256  }
257 
258  for (t = 20; t < 40; t++)
259  {
260  temp = SHA1CircularShift (5, A) + (B ^ C ^ D) + E + W[t] + K[1];
261  temp &= 0xFFFFFFFF;
262  E = D;
263  D = C;
264  C = SHA1CircularShift (30, B);
265  B = A;
266  A = temp;
267  }
268 
269  for (t = 40; t < 60; t++)
270  {
271  temp = SHA1CircularShift (5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
272  temp &= 0xFFFFFFFF;
273  E = D;
274  D = C;
275  C = SHA1CircularShift (30, B);
276  B = A;
277  A = temp;
278  }
279 
280  for (t = 60; t < 80; t++)
281  {
282  temp = SHA1CircularShift (5, A) + (B ^ C ^ D) + E + W[t] + K[3];
283  temp &= 0xFFFFFFFF;
284  E = D;
285  D = C;
286  C = SHA1CircularShift (30, B);
287  B = A;
288  A = temp;
289  }
290 
291  context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;
292  context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;
293  context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;
294  context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;
295  context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;
296 
297  context->Message_Block_Index = 0;
298 }
299 
300 /*
301  * SHA1PadMessage
302  *
303  * Description:
304  * According to the standard, the message must be padded to an even
305  * 512 bits. The first padding bit must be a '1'. The last 64
306  * bits represent the length of the original message. All bits in
307  * between should be 0. This function will pad the message
308  * according to those rules by filling the Message_Block array
309  * accordingly. It will also call SHA1ProcessMessageBlock()
310  * appropriately. When it returns, it can be assumed that the
311  * message digest has been computed.
312  *
313  * Parameters:
314  * context: [in/out]
315  * The context to pad
316  *
317  * Returns:
318  * Nothing.
319  *
320  * Comments:
321  *
322  */
323 void
325 {
326  /*
327  * Check to see if the current message block is too small to hold
328  * the initial padding bits and length. If so, we will pad the
329  * block, process it, and then continue padding into a second
330  * block.
331  */
332  if (context->Message_Block_Index > 55)
333  {
334  context->Message_Block[context->Message_Block_Index++] = 0x80;
335  while (context->Message_Block_Index < 64)
336  {
337  context->Message_Block[context->Message_Block_Index++] = 0;
338  }
339 
340  SHA1ProcessMessageBlock (context);
341 
342  while (context->Message_Block_Index < 56)
343  {
344  context->Message_Block[context->Message_Block_Index++] = 0;
345  }
346  }
347  else
348  {
349  context->Message_Block[context->Message_Block_Index++] = 0x80;
350  while (context->Message_Block_Index < 56)
351  {
352  context->Message_Block[context->Message_Block_Index++] = 0;
353  }
354  }
355 
356  /*
357  * Store the message length as the last 8 octets
358  */
359  context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
360  context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
361  context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
362  context->Message_Block[59] = (context->Length_High) & 0xFF;
363  context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
364  context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
365  context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
366  context->Message_Block[63] = (context->Length_Low) & 0xFF;
367 
368  SHA1ProcessMessageBlock (context);
369 }
370 
371 int
372 SHA1Compute (const unsigned char *message_array, size_t length, SHA1Hash * hash)
373 {
374  SHA1Context context;
375 
376  assert (message_array != NULL);
377  assert (hash != NULL);
378 
379  SHA1Reset (&context);
380  SHA1Input (&context, message_array, length);
381 
382  if (!SHA1Result (&context))
383  {
384  assert (false);
385  /* TODO: Set an appropriate error message. */
387  return ER_FAILED;
388  }
389 
390  hash->h[0] = (INT32) context.Message_Digest[0];
391  hash->h[1] = (INT32) context.Message_Digest[1];
392  hash->h[2] = (INT32) context.Message_Digest[2];
393  hash->h[3] = (INT32) context.Message_Digest[3];
394  hash->h[4] = (INT32) context.Message_Digest[4];
395 
396  return NO_ERROR;
397 }
398 
399 int
400 SHA1Compare (void *a, void *b)
401 {
402  SHA1Hash *a_hash = (SHA1Hash *) a;
403  SHA1Hash *b_hash = (SHA1Hash *) b;
404  INT32 diff;
405  int i;
406 
407  for (i = 0; i < 5; i++)
408  {
409  diff = a_hash->h[i] - b_hash->h[i];
410  if (diff != 0)
411  {
412  return diff;
413  }
414  }
415  return 0;
416 }
Definition: sha1.h:50
#define SHA1CircularShift(bits, word)
Definition: sha1.c:49
#define NO_ERROR
Definition: error_code.h:46
INT32 h[5]
Definition: sha1.h:52
void SHA1ProcessMessageBlock(SHA1Context *)
Definition: sha1.c:211
#define ER_FAILED
Definition: error_code.h:47
void SHA1PadMessage(SHA1Context *)
Definition: sha1.c:324
int SHA1Result(SHA1Context *context)
Definition: sha1.c:109
#define diff
Definition: mprec.h:352
int SHA1Compute(const unsigned char *message_array, size_t length, SHA1Hash *hash)
Definition: sha1.c:372
unsigned Message_Digest[5]
Definition: sha1.h:35
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
#define assert(x)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
unsigned Length_Low
Definition: sha1.h:37
int Computed
Definition: sha1.h:43
#define NULL
Definition: freelistheap.h:34
void SHA1Input(SHA1Context *context, const unsigned char *message_array, size_t length)
Definition: sha1.c:149
int Corrupted
Definition: sha1.h:44
#define ARG_FILE_LINE
Definition: error_manager.h:44
int Message_Block_Index
Definition: sha1.h:41
unsigned char Message_Block[64]
Definition: sha1.h:40
int i
Definition: dynamic_load.c:954
int SHA1Compare(void *a, void *b)
Definition: sha1.c:400
unsigned Length_High
Definition: sha1.h:38
void SHA1Reset(SHA1Context *context)
Definition: sha1.c:75