~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/sha1.c

  • Committer: Monty Taylor
  • Date: 2008-08-04 22:01:39 UTC
  • mto: (261.1.4 drizzle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804220139-fy862jc9lykayvka
Moved libdrizzle.ver.in to libdrizzle.ver.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2002, 2004, 2006 MySQL AB
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/*
 
17
  Original Source from: http://www.faqs.org/rfcs/rfc3174.html
 
18
 
 
19
 DESCRIPTION
 
20
   This file implements the Secure Hashing Algorithm 1 as
 
21
   defined in FIPS PUB 180-1 published April 17, 1995.
 
22
 
 
23
   The SHA-1, produces a 160-bit message digest for a given data
 
24
   stream.  It should take about 2**n steps to find a message with the
 
25
   same digest as a given message and 2**(n/2) to find any two
 
26
   messages with the same digest, when n is the digest size in bits.
 
27
   Therefore, this algorithm can serve as a means of providing a
 
28
   "fingerprint" for a message.
 
29
 
 
30
 PORTABILITY ISSUES
 
31
   SHA-1 is defined in terms of 32-bit "words".  This code uses
 
32
   <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned
 
33
   integer types.  If your C compiler does not support 32 bit unsigned
 
34
   integers, this code is not appropriate.
 
35
 
 
36
 CAVEATS
 
37
   SHA-1 is designed to work with messages less than 2^64 bits long.
 
38
   Although SHA-1 allows a message digest to be generated for messages
 
39
   of any number of bits less than 2^64, this implementation only
 
40
   works with messages with a length that is a multiple of the size of
 
41
   an 8-bit character.
 
42
 
 
43
  CHANGES
 
44
    2002 by Peter Zaitsev to
 
45
     - fit to new prototypes according to MySQL standard
 
46
     - Some optimizations
 
47
     - All checking is now done in debug only mode
 
48
     - More comments
 
49
*/
 
50
 
 
51
#include <mystrings/m_string.h>
 
52
#include "sha1.h"
 
53
 
 
54
/*
 
55
  Define the SHA1 circular left shift macro
 
56
*/
 
57
 
 
58
#define SHA1CircularShift(bits,word) \
 
59
                (((word) << (bits)) | ((word) >> (32-(bits))))
 
60
 
 
61
/* Local Function Prototyptes */
 
62
static void SHA1PadMessage(SHA1_CONTEXT*);
 
63
static void SHA1ProcessMessageBlock(SHA1_CONTEXT*);
 
64
 
 
65
 
 
66
/*
 
67
  Initialize SHA1Context
 
68
 
 
69
  SYNOPSIS
 
70
    mysql_sha1_reset()
 
71
    context [in/out]            The context to reset.
 
72
 
 
73
 DESCRIPTION
 
74
   This function will initialize the SHA1Context in preparation
 
75
   for computing a new SHA1 message digest.
 
76
 
 
77
 RETURN
 
78
   SHA_SUCCESS          ok
 
79
   != SHA_SUCCESS       sha Error Code.
 
80
*/
 
81
 
 
82
 
 
83
const uint32_t sha_const_key[5]=
 
84
{
 
85
  0x67452301,
 
86
  0xEFCDAB89,
 
87
  0x98BADCFE,
 
88
  0x10325476,
 
89
  0xC3D2E1F0
 
90
};
 
91
 
 
92
 
 
93
int mysql_sha1_reset(SHA1_CONTEXT *context)
 
94
{
 
95
  context->Length                 = 0;
 
96
  context->Message_Block_Index    = 0;
 
97
 
 
98
  context->Intermediate_Hash[0]   = sha_const_key[0];
 
99
  context->Intermediate_Hash[1]   = sha_const_key[1];
 
100
  context->Intermediate_Hash[2]   = sha_const_key[2];
 
101
  context->Intermediate_Hash[3]   = sha_const_key[3];
 
102
  context->Intermediate_Hash[4]   = sha_const_key[4];
 
103
 
 
104
  context->Computed   = 0;
 
105
  context->Corrupted  = 0;
 
106
 
 
107
  return SHA_SUCCESS;
 
108
}
 
109
 
 
110
 
 
111
/*
 
112
   Return the 160-bit message digest into the array provided by the caller
 
113
 
 
114
  SYNOPSIS
 
115
    mysql_sha1_result()
 
116
    context [in/out]            The context to use to calculate the SHA-1 hash.
 
117
    Message_Digest: [out]       Where the digest is returned.
 
118
 
 
119
  DESCRIPTION
 
120
    NOTE: The first octet of hash is stored in the 0th element,
 
121
          the last octet of hash in the 19th element.
 
122
 
 
123
 RETURN
 
124
   SHA_SUCCESS          ok
 
125
   != SHA_SUCCESS       sha Error Code.
 
126
*/
 
127
 
 
128
int mysql_sha1_result(SHA1_CONTEXT *context,
 
129
                      uint8_t Message_Digest[SHA1_HASH_SIZE])
 
130
{
 
131
  int i;
 
132
 
 
133
  if (!context->Computed)
 
134
  {
 
135
    SHA1PadMessage(context);
 
136
     /* message may be sensitive, clear it out */
 
137
    memset((char*) context->Message_Block, 0, 64);
 
138
    context->Length   = 0;    /* and clear length  */
 
139
    context->Computed = 1;
 
140
  }
 
141
 
 
142
  for (i = 0; i < SHA1_HASH_SIZE; i++)
 
143
    Message_Digest[i] = (int8_t)((context->Intermediate_Hash[i>>2] >> 8
 
144
                         * ( 3 - ( i & 0x03 ) )));
 
145
  return SHA_SUCCESS;
 
146
}
 
147
 
 
148
 
 
149
/*
 
150
  Accepts an array of octets as the next portion of the message.
 
151
 
 
152
  SYNOPSIS
 
153
   mysql_sha1_input()
 
154
   context [in/out]     The SHA context to update
 
155
   message_array        An array of characters representing the next portion
 
156
                        of the message.
 
157
  length                The length of the message in message_array
 
158
 
 
159
 RETURN
 
160
   SHA_SUCCESS          ok
 
161
   != SHA_SUCCESS       sha Error Code.
 
162
*/
 
163
 
 
164
int mysql_sha1_input(SHA1_CONTEXT *context, const uint8_t *message_array,
 
165
                     unsigned length)
 
166
{
 
167
  if (!length)
 
168
    return SHA_SUCCESS;
 
169
 
 
170
  while (length--)
 
171
  {
 
172
    context->Message_Block[context->Message_Block_Index++]=
 
173
      (*message_array & 0xFF);
 
174
    context->Length  += 8;  /* Length is in bits */
 
175
 
 
176
    if (context->Message_Block_Index == 64)
 
177
    {
 
178
      SHA1ProcessMessageBlock(context);
 
179
    }
 
180
    message_array++;
 
181
  }
 
182
  return SHA_SUCCESS;
 
183
}
 
184
 
 
185
 
 
186
/*
 
187
  Process the next 512 bits of the message stored in the Message_Block array.
 
188
 
 
189
  SYNOPSIS
 
190
    SHA1ProcessMessageBlock()
 
191
 
 
192
   DESCRIPTION
 
193
     Many of the variable names in this code, especially the single
 
194
     character names, were used because those were the names used in
 
195
     the publication.
 
196
*/
 
197
 
 
198
/* Constants defined in SHA-1   */
 
199
static const uint32_t  K[]=
 
200
{
 
201
  0x5A827999,
 
202
  0x6ED9EBA1,
 
203
  0x8F1BBCDC,
 
204
  0xCA62C1D6
 
205
};
 
206
 
 
207
 
 
208
static void SHA1ProcessMessageBlock(SHA1_CONTEXT *context)
 
209
{
 
210
  int           t;                 /* Loop counter                */
 
211
  uint32_t      temp;              /* Temporary word value        */
 
212
  uint32_t      W[80];             /* Word sequence               */
 
213
  uint32_t      A, B, C, D, E;     /* Word buffers                */
 
214
  int idx;
 
215
 
 
216
  /*
 
217
    Initialize the first 16 words in the array W
 
218
  */
 
219
 
 
220
  for (t = 0; t < 16; t++)
 
221
  {
 
222
    idx=t*4;
 
223
    W[t] = context->Message_Block[idx] << 24;
 
224
    W[t] |= context->Message_Block[idx + 1] << 16;
 
225
    W[t] |= context->Message_Block[idx + 2] << 8;
 
226
    W[t] |= context->Message_Block[idx + 3];
 
227
  }
 
228
 
 
229
 
 
230
  for (t = 16; t < 80; t++)
 
231
  {
 
232
    W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
 
233
  }
 
234
 
 
235
  A = context->Intermediate_Hash[0];
 
236
  B = context->Intermediate_Hash[1];
 
237
  C = context->Intermediate_Hash[2];
 
238
  D = context->Intermediate_Hash[3];
 
239
  E = context->Intermediate_Hash[4];
 
240
 
 
241
  for (t = 0; t < 20; t++)
 
242
  {
 
243
    temp= SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
 
244
    E = D;
 
245
    D = C;
 
246
    C = SHA1CircularShift(30,B);
 
247
    B = A;
 
248
    A = temp;
 
249
  }
 
250
 
 
251
  for (t = 20; t < 40; t++)
 
252
  {
 
253
    temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
 
254
    E = D;
 
255
    D = C;
 
256
    C = SHA1CircularShift(30,B);
 
257
    B = A;
 
258
    A = temp;
 
259
  }
 
260
 
 
261
  for (t = 40; t < 60; t++)
 
262
  {
 
263
    temp= (SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] +
 
264
           K[2]);
 
265
    E = D;
 
266
    D = C;
 
267
    C = SHA1CircularShift(30,B);
 
268
    B = A;
 
269
    A = temp;
 
270
  }
 
271
 
 
272
  for (t = 60; t < 80; t++)
 
273
  {
 
274
    temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
 
275
    E = D;
 
276
    D = C;
 
277
    C = SHA1CircularShift(30,B);
 
278
    B = A;
 
279
    A = temp;
 
280
  }
 
281
 
 
282
  context->Intermediate_Hash[0] += A;
 
283
  context->Intermediate_Hash[1] += B;
 
284
  context->Intermediate_Hash[2] += C;
 
285
  context->Intermediate_Hash[3] += D;
 
286
  context->Intermediate_Hash[4] += E;
 
287
 
 
288
  context->Message_Block_Index = 0;
 
289
}
 
290
 
 
291
 
 
292
/*
 
293
  Pad message
 
294
 
 
295
  SYNOPSIS
 
296
    SHA1PadMessage()
 
297
    context: [in/out]           The context to pad
 
298
 
 
299
  DESCRIPTION
 
300
    According to the standard, the message must be padded to an even
 
301
    512 bits.  The first padding bit must be a '1'. The last 64 bits
 
302
    represent the length of the original message.  All bits in between
 
303
    should be 0.  This function will pad the message according to
 
304
    those rules by filling the Message_Block array accordingly.  It
 
305
    will also call the ProcessMessageBlock function provided
 
306
    appropriately. When it returns, it can be assumed that the message
 
307
    digest has been computed.
 
308
 
 
309
*/
 
310
 
 
311
static void SHA1PadMessage(SHA1_CONTEXT *context)
 
312
{
 
313
  /*
 
314
    Check to see if the current message block is too small to hold
 
315
    the initial padding bits and length.  If so, we will pad the
 
316
    block, process it, and then continue padding into a second
 
317
    block.
 
318
  */
 
319
 
 
320
  int i=context->Message_Block_Index;
 
321
 
 
322
  if (i > 55)
 
323
  {
 
324
    context->Message_Block[i++] = 0x80;
 
325
    memset((char*) &context->Message_Block[i], 0,
 
326
          sizeof(context->Message_Block[0])*(64-i));
 
327
    context->Message_Block_Index=64;
 
328
 
 
329
    /* This function sets context->Message_Block_Index to zero  */
 
330
    SHA1ProcessMessageBlock(context);
 
331
 
 
332
    memset((char*) &context->Message_Block[0], 0,
 
333
          sizeof(context->Message_Block[0])*56);
 
334
    context->Message_Block_Index=56;
 
335
  }
 
336
  else
 
337
  {
 
338
    context->Message_Block[i++] = 0x80;
 
339
    memset((char*) &context->Message_Block[i], 0,
 
340
          sizeof(context->Message_Block[0])*(56-i));
 
341
    context->Message_Block_Index=56;
 
342
  }
 
343
 
 
344
  /*
 
345
    Store the message length as the last 8 octets
 
346
  */
 
347
 
 
348
  context->Message_Block[56] = (int8_t) (context->Length >> 56);
 
349
  context->Message_Block[57] = (int8_t) (context->Length >> 48);
 
350
  context->Message_Block[58] = (int8_t) (context->Length >> 40);
 
351
  context->Message_Block[59] = (int8_t) (context->Length >> 32);
 
352
  context->Message_Block[60] = (int8_t) (context->Length >> 24);
 
353
  context->Message_Block[61] = (int8_t) (context->Length >> 16);
 
354
  context->Message_Block[62] = (int8_t) (context->Length >> 8);
 
355
  context->Message_Block[63] = (int8_t) (context->Length);
 
356
 
 
357
  SHA1ProcessMessageBlock(context);
 
358
}