~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to mysys/sha1.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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 "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
}