~vlad-lesin/percona-server/mysql-5.0.33-original

« back to all changes in this revision

Viewing changes to mysys/sha1.c

  • Committer: Vlad Lesin
  • Date: 2012-07-31 09:21:34 UTC
  • Revision ID: vladislav.lesin@percona.com-20120731092134-zfodx022b7992wsi
VirginĀ 5.0.33

Show diffs side-by-side

added added

removed removed

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