~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/sha1.cc

  • Committer: Brian Aker
  • Date: 2009-10-12 06:15:02 UTC
  • mfrom: (1165.1.178 static-functions)
  • Revision ID: brian@gaz-20091012061502-cds4m0cya7ow8sj7
Merge Stewart

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(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(&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(&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(&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
 
}