~drizzle-trunk/drizzle/development

1 by brian
clean slate
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 "my_global.h"
52
#include "m_string.h"
53
#include "sha1.h"
54
55
/*
56
  Define the SHA1 circular left shift macro
57
*/
58
59
#define SHA1CircularShift(bits,word) \
60
		(((word) << (bits)) | ((word) >> (32-(bits))))
61
62
/* Local Function Prototyptes */
63
static void SHA1PadMessage(SHA1_CONTEXT*);
64
static void SHA1ProcessMessageBlock(SHA1_CONTEXT*);
65
66
67
/*
68
  Initialize SHA1Context
69
70
  SYNOPSIS
71
    mysql_sha1_reset()
72
    context [in/out]		The context to reset.
73
74
 DESCRIPTION
75
   This function will initialize the SHA1Context in preparation
76
   for computing a new SHA1 message digest.
77
78
 RETURN
79
   SHA_SUCCESS		ok
80
   != SHA_SUCCESS	sha Error Code.
81
*/
82
83
84
const uint32 sha_const_key[5]=
85
{
86
  0x67452301,
87
  0xEFCDAB89,
88
  0x98BADCFE,
89
  0x10325476,
90
  0xC3D2E1F0
91
};
92
93
94
int mysql_sha1_reset(SHA1_CONTEXT *context)
95
{
96
#ifndef DBUG_OFF
97
  if (!context)
98
    return SHA_NULL;
99
#endif
100
101
  context->Length		  = 0;
102
  context->Message_Block_Index	  = 0;
103
104
  context->Intermediate_Hash[0]   = sha_const_key[0];
105
  context->Intermediate_Hash[1]   = sha_const_key[1];
106
  context->Intermediate_Hash[2]   = sha_const_key[2];
107
  context->Intermediate_Hash[3]   = sha_const_key[3];
108
  context->Intermediate_Hash[4]   = sha_const_key[4];
109
110
  context->Computed   = 0;
111
  context->Corrupted  = 0;
112
113
  return SHA_SUCCESS;
114
}
115
116
117
/*
118
   Return the 160-bit message digest into the array provided by the caller
119
120
  SYNOPSIS
121
    mysql_sha1_result()
122
    context [in/out]		The context to use to calculate the SHA-1 hash.
123
    Message_Digest: [out]	Where the digest is returned.
124
125
  DESCRIPTION
126
    NOTE: The first octet of hash is stored in the 0th element,
127
	  the last octet of hash in the 19th element.
128
129
 RETURN
130
   SHA_SUCCESS		ok
131
   != SHA_SUCCESS	sha Error Code.
132
*/
133
134
int mysql_sha1_result(SHA1_CONTEXT *context,
135
                      uint8 Message_Digest[SHA1_HASH_SIZE])
136
{
137
  int i;
138
139
#ifndef DBUG_OFF
140
  if (!context || !Message_Digest)
141
    return SHA_NULL;
142
143
  if (context->Corrupted)
144
    return context->Corrupted;
145
#endif
146
147
  if (!context->Computed)
148
  {
149
    SHA1PadMessage(context);
150
     /* message may be sensitive, clear it out */
151
    bzero((char*) context->Message_Block,64);
152
    context->Length   = 0;    /* and clear length  */
153
    context->Computed = 1;
154
  }
155
156
  for (i = 0; i < SHA1_HASH_SIZE; i++)
157
    Message_Digest[i] = (int8)((context->Intermediate_Hash[i>>2] >> 8
158
			 * ( 3 - ( i & 0x03 ) )));
159
  return SHA_SUCCESS;
160
}
161
162
163
/*
164
  Accepts an array of octets as the next portion of the message.
165
166
  SYNOPSIS
167
   mysql_sha1_input()
168
   context [in/out]	The SHA context to update
169
   message_array	An array of characters representing the next portion
170
			of the message.
171
  length		The length of the message in message_array
172
173
 RETURN
174
   SHA_SUCCESS		ok
175
   != SHA_SUCCESS	sha Error Code.
176
*/
177
178
int mysql_sha1_input(SHA1_CONTEXT *context, const uint8 *message_array,
179
                     unsigned length)
180
{
181
  if (!length)
182
    return SHA_SUCCESS;
183
184
#ifndef DBUG_OFF
185
  /* We assume client konows what it is doing in non-debug mode */
186
  if (!context || !message_array)
187
    return SHA_NULL;
188
  if (context->Computed)
189
    return (context->Corrupted= SHA_STATE_ERROR);
190
  if (context->Corrupted)
191
    return context->Corrupted;
192
#endif
193
194
  while (length--)
195
  {
196
    context->Message_Block[context->Message_Block_Index++]=
197
      (*message_array & 0xFF);
198
    context->Length  += 8;  /* Length is in bits */
199
200
#ifndef DBUG_OFF
201
    /*
202
      Then we're not debugging we assume we never will get message longer
203
      2^64 bits.
204
    */
205
    if (context->Length == 0)
206
      return (context->Corrupted= 1);	   /* Message is too long */
207
#endif
208
209
    if (context->Message_Block_Index == 64)
210
    {
211
      SHA1ProcessMessageBlock(context);
212
    }
213
    message_array++;
214
  }
215
  return SHA_SUCCESS;
216
}
217
218
219
/*
220
  Process the next 512 bits of the message stored in the Message_Block array.
221
222
  SYNOPSIS
223
    SHA1ProcessMessageBlock()
224
225
   DESCRIPTION
226
     Many of the variable names in this code, especially the single
227
     character names, were used because those were the names used in
228
     the publication.
229
*/
230
231
/* Constants defined in SHA-1	*/
232
static const uint32  K[]=
233
{
234
  0x5A827999,
235
  0x6ED9EBA1,
236
  0x8F1BBCDC,
237
  0xCA62C1D6
238
};
239
240
241
static void SHA1ProcessMessageBlock(SHA1_CONTEXT *context)
242
{
243
  int		t;		   /* Loop counter		  */
244
  uint32	temp;		   /* Temporary word value	  */
245
  uint32	W[80];		   /* Word sequence		  */
246
  uint32	A, B, C, D, E;	   /* Word buffers		  */
247
  int idx;
248
249
  /*
250
    Initialize the first 16 words in the array W
251
  */
252
253
  for (t = 0; t < 16; t++)
254
  {
255
    idx=t*4;
256
    W[t] = context->Message_Block[idx] << 24;
257
    W[t] |= context->Message_Block[idx + 1] << 16;
258
    W[t] |= context->Message_Block[idx + 2] << 8;
259
    W[t] |= context->Message_Block[idx + 3];
260
  }
261
262
263
  for (t = 16; t < 80; t++)
264
  {
265
    W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
266
  }
267
268
  A = context->Intermediate_Hash[0];
269
  B = context->Intermediate_Hash[1];
270
  C = context->Intermediate_Hash[2];
271
  D = context->Intermediate_Hash[3];
272
  E = context->Intermediate_Hash[4];
273
274
  for (t = 0; t < 20; t++)
275
  {
276
    temp= SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
277
    E = D;
278
    D = C;
279
    C = SHA1CircularShift(30,B);
280
    B = A;
281
    A = temp;
282
  }
283
284
  for (t = 20; t < 40; t++)
285
  {
286
    temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
287
    E = D;
288
    D = C;
289
    C = SHA1CircularShift(30,B);
290
    B = A;
291
    A = temp;
292
  }
293
294
  for (t = 40; t < 60; t++)
295
  {
296
    temp= (SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] +
297
	   K[2]);
298
    E = D;
299
    D = C;
300
    C = SHA1CircularShift(30,B);
301
    B = A;
302
    A = temp;
303
  }
304
305
  for (t = 60; t < 80; t++)
306
  {
307
    temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
308
    E = D;
309
    D = C;
310
    C = SHA1CircularShift(30,B);
311
    B = A;
312
    A = temp;
313
  }
314
315
  context->Intermediate_Hash[0] += A;
316
  context->Intermediate_Hash[1] += B;
317
  context->Intermediate_Hash[2] += C;
318
  context->Intermediate_Hash[3] += D;
319
  context->Intermediate_Hash[4] += E;
320
321
  context->Message_Block_Index = 0;
322
}
323
324
325
/*
326
  Pad message
327
328
  SYNOPSIS
329
    SHA1PadMessage()
330
    context: [in/out]		The context to pad
331
332
  DESCRIPTION
333
    According to the standard, the message must be padded to an even
334
    512 bits.  The first padding bit must be a '1'. The last 64 bits
335
    represent the length of the original message.  All bits in between
336
    should be 0.  This function will pad the message according to
337
    those rules by filling the Message_Block array accordingly.  It
338
    will also call the ProcessMessageBlock function provided
339
    appropriately. When it returns, it can be assumed that the message
340
    digest has been computed.
341
342
*/
343
344
static void SHA1PadMessage(SHA1_CONTEXT *context)
345
{
346
  /*
347
    Check to see if the current message block is too small to hold
348
    the initial padding bits and length.  If so, we will pad the
349
    block, process it, and then continue padding into a second
350
    block.
351
  */
352
353
  int i=context->Message_Block_Index;
354
355
  if (i > 55)
356
  {
357
    context->Message_Block[i++] = 0x80;
358
    bzero((char*) &context->Message_Block[i],
359
	  sizeof(context->Message_Block[0])*(64-i));
360
    context->Message_Block_Index=64;
361
362
    /* This function sets context->Message_Block_Index to zero	*/
363
    SHA1ProcessMessageBlock(context);
364
365
    bzero((char*) &context->Message_Block[0],
366
	  sizeof(context->Message_Block[0])*56);
367
    context->Message_Block_Index=56;
368
  }
369
  else
370
  {
371
    context->Message_Block[i++] = 0x80;
372
    bzero((char*) &context->Message_Block[i],
373
	  sizeof(context->Message_Block[0])*(56-i));
374
    context->Message_Block_Index=56;
375
  }
376
377
  /*
378
    Store the message length as the last 8 octets
379
  */
380
381
  context->Message_Block[56] = (int8) (context->Length >> 56);
382
  context->Message_Block[57] = (int8) (context->Length >> 48);
383
  context->Message_Block[58] = (int8) (context->Length >> 40);
384
  context->Message_Block[59] = (int8) (context->Length >> 32);
385
  context->Message_Block[60] = (int8) (context->Length >> 24);
386
  context->Message_Block[61] = (int8) (context->Length >> 16);
387
  context->Message_Block[62] = (int8) (context->Length >> 8);
388
  context->Message_Block[63] = (int8) (context->Length);
389
390
  SHA1ProcessMessageBlock(context);
391
}