~ubuntu-branches/ubuntu/oneiric/likewise-open/oneiric

« back to all changes in this revision

Viewing changes to openssl/crypto/md32_common.h

  • Committer: Bazaar Package Importer
  • Author(s): Scott Salley
  • Date: 2010-11-22 12:06:00 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122120600-8lba1fpceot71wlb
Tags: 6.0.0.53010-1
Likewise Open 6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* crypto/md32_common.h */
 
2
/* ====================================================================
 
3
 * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer. 
 
11
 *
 
12
 * 2. Redistributions in binary form must reproduce the above copyright
 
13
 *    notice, this list of conditions and the following disclaimer in
 
14
 *    the documentation and/or other materials provided with the
 
15
 *    distribution.
 
16
 *
 
17
 * 3. All advertising materials mentioning features or use of this
 
18
 *    software must display the following acknowledgment:
 
19
 *    "This product includes software developed by the OpenSSL Project
 
20
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 
21
 *
 
22
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 
23
 *    endorse or promote products derived from this software without
 
24
 *    prior written permission. For written permission, please contact
 
25
 *    licensing@OpenSSL.org.
 
26
 *
 
27
 * 5. Products derived from this software may not be called "OpenSSL"
 
28
 *    nor may "OpenSSL" appear in their names without prior written
 
29
 *    permission of the OpenSSL Project.
 
30
 *
 
31
 * 6. Redistributions of any form whatsoever must retain the following
 
32
 *    acknowledgment:
 
33
 *    "This product includes software developed by the OpenSSL Project
 
34
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 
35
 *
 
36
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 
37
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
39
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 
40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
42
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
43
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
44
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
45
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
46
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
47
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 
48
 * ====================================================================
 
49
 *
 
50
 */
 
51
 
 
52
/*
 
53
 * This is a generic 32 bit "collector" for message digest algorithms.
 
54
 * Whenever needed it collects input character stream into chunks of
 
55
 * 32 bit values and invokes a block function that performs actual hash
 
56
 * calculations.
 
57
 *
 
58
 * Porting guide.
 
59
 *
 
60
 * Obligatory macros:
 
61
 *
 
62
 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
 
63
 *      this macro defines byte order of input stream.
 
64
 * HASH_CBLOCK
 
65
 *      size of a unit chunk HASH_BLOCK operates on.
 
66
 * HASH_LONG
 
67
 *      has to be at lest 32 bit wide, if it's wider, then
 
68
 *      HASH_LONG_LOG2 *has to* be defined along
 
69
 * HASH_CTX
 
70
 *      context structure that at least contains following
 
71
 *      members:
 
72
 *              typedef struct {
 
73
 *                      ...
 
74
 *                      HASH_LONG       Nl,Nh;
 
75
 *                      either {
 
76
 *                      HASH_LONG       data[HASH_LBLOCK];
 
77
 *                      unsigned char   data[HASH_CBLOCK];
 
78
 *                      };
 
79
 *                      unsigned int    num;
 
80
 *                      ...
 
81
 *                      } HASH_CTX;
 
82
 *      data[] vector is expected to be zeroed upon first call to
 
83
 *      HASH_UPDATE.
 
84
 * HASH_UPDATE
 
85
 *      name of "Update" function, implemented here.
 
86
 * HASH_TRANSFORM
 
87
 *      name of "Transform" function, implemented here.
 
88
 * HASH_FINAL
 
89
 *      name of "Final" function, implemented here.
 
90
 * HASH_BLOCK_DATA_ORDER
 
91
 *      name of "block" function capable of treating *unaligned* input
 
92
 *      message in original (data) byte order, implemented externally.
 
93
 * HASH_MAKE_STRING
 
94
 *      macro convering context variables to an ASCII hash string.
 
95
 *
 
96
 * MD5 example:
 
97
 *
 
98
 *      #define DATA_ORDER_IS_LITTLE_ENDIAN
 
99
 *
 
100
 *      #define HASH_LONG               MD5_LONG
 
101
 *      #define HASH_LONG_LOG2          MD5_LONG_LOG2
 
102
 *      #define HASH_CTX                MD5_CTX
 
103
 *      #define HASH_CBLOCK             MD5_CBLOCK
 
104
 *      #define HASH_UPDATE             MD5_Update
 
105
 *      #define HASH_TRANSFORM          MD5_Transform
 
106
 *      #define HASH_FINAL              MD5_Final
 
107
 *      #define HASH_BLOCK_DATA_ORDER   md5_block_data_order
 
108
 *
 
109
 *                                      <appro@fy.chalmers.se>
 
110
 */
 
111
 
 
112
#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
 
113
#error "DATA_ORDER must be defined!"
 
114
#endif
 
115
 
 
116
#ifndef HASH_CBLOCK
 
117
#error "HASH_CBLOCK must be defined!"
 
118
#endif
 
119
#ifndef HASH_LONG
 
120
#error "HASH_LONG must be defined!"
 
121
#endif
 
122
#ifndef HASH_CTX
 
123
#error "HASH_CTX must be defined!"
 
124
#endif
 
125
 
 
126
#ifndef HASH_UPDATE
 
127
#error "HASH_UPDATE must be defined!"
 
128
#endif
 
129
#ifndef HASH_TRANSFORM
 
130
#error "HASH_TRANSFORM must be defined!"
 
131
#endif
 
132
#ifndef HASH_FINAL
 
133
#error "HASH_FINAL must be defined!"
 
134
#endif
 
135
 
 
136
#ifndef HASH_BLOCK_DATA_ORDER
 
137
#error "HASH_BLOCK_DATA_ORDER must be defined!"
 
138
#endif
 
139
 
 
140
/*
 
141
 * Engage compiler specific rotate intrinsic function if available.
 
142
 */
 
143
#undef ROTATE
 
144
#ifndef PEDANTIC
 
145
# if defined(_MSC_VER) || defined(__ICC)
 
146
#  define ROTATE(a,n)   _lrotl(a,n)
 
147
# elif defined(__MWERKS__)
 
148
#  if defined(__POWERPC__)
 
149
#   define ROTATE(a,n)  __rlwinm(a,n,0,31)
 
150
#  elif defined(__MC68K__)
 
151
    /* Motorola specific tweak. <appro@fy.chalmers.se> */
 
152
#   define ROTATE(a,n)  ( n<24 ? __rol(a,n) : __ror(a,32-n) )
 
153
#  else
 
154
#   define ROTATE(a,n)  __rol(a,n)
 
155
#  endif
 
156
# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
 
157
  /*
 
158
   * Some GNU C inline assembler templates. Note that these are
 
159
   * rotates by *constant* number of bits! But that's exactly
 
160
   * what we need here...
 
161
   *                                    <appro@fy.chalmers.se>
 
162
   */
 
163
#  if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
 
164
#   define ROTATE(a,n)  ({ register unsigned int ret;   \
 
165
                                asm (                   \
 
166
                                "roll %1,%0"            \
 
167
                                : "=r"(ret)             \
 
168
                                : "I"(n), "0"(a)        \
 
169
                                : "cc");                \
 
170
                           ret;                         \
 
171
                        })
 
172
#  elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
 
173
        defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
 
174
#   define ROTATE(a,n)  ({ register unsigned int ret;   \
 
175
                                asm (                   \
 
176
                                "rlwinm %0,%1,%2,0,31"  \
 
177
                                : "=r"(ret)             \
 
178
                                : "r"(a), "I"(n));      \
 
179
                           ret;                         \
 
180
                        })
 
181
#  elif defined(__s390x__)
 
182
#   define ROTATE(a,n) ({ register unsigned int ret;    \
 
183
                                asm ("rll %0,%1,%2"     \
 
184
                                : "=r"(ret)             \
 
185
                                : "r"(a), "I"(n));      \
 
186
                          ret;                          \
 
187
                        })
 
188
#  endif
 
189
# endif
 
190
#endif /* PEDANTIC */
 
191
 
 
192
#ifndef ROTATE
 
193
#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
 
194
#endif
 
195
 
 
196
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
 
197
 
 
198
#ifndef PEDANTIC
 
199
# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
 
200
#  if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
 
201
      (defined(__x86_64) || defined(__x86_64__))
 
202
#   if !defined(B_ENDIAN)
 
203
    /*
 
204
     * This gives ~30-40% performance improvement in SHA-256 compiled
 
205
     * with gcc [on P4]. Well, first macro to be frank. We can pull
 
206
     * this trick on x86* platforms only, because these CPUs can fetch
 
207
     * unaligned data without raising an exception.
 
208
     */
 
209
#   define HOST_c2l(c,l)        ({ unsigned int r=*((const unsigned int *)(c)); \
 
210
                                   asm ("bswapl %0":"=r"(r):"0"(r));    \
 
211
                                   (c)+=4; (l)=r;                       })
 
212
#   define HOST_l2c(l,c)        ({ unsigned int r=(l);                  \
 
213
                                   asm ("bswapl %0":"=r"(r):"0"(r));    \
 
214
                                   *((unsigned int *)(c))=r; (c)+=4; r; })
 
215
#   endif
 
216
#  endif
 
217
# endif
 
218
#endif
 
219
#if defined(__s390__) || defined(__s390x__)
 
220
# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
 
221
# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
 
222
#endif
 
223
 
 
224
#ifndef HOST_c2l
 
225
#define HOST_c2l(c,l)   (l =(((unsigned long)(*((c)++)))<<24),          \
 
226
                         l|=(((unsigned long)(*((c)++)))<<16),          \
 
227
                         l|=(((unsigned long)(*((c)++)))<< 8),          \
 
228
                         l|=(((unsigned long)(*((c)++)))    ),          \
 
229
                         l)
 
230
#endif
 
231
#ifndef HOST_l2c
 
232
#define HOST_l2c(l,c)   (*((c)++)=(unsigned char)(((l)>>24)&0xff),      \
 
233
                         *((c)++)=(unsigned char)(((l)>>16)&0xff),      \
 
234
                         *((c)++)=(unsigned char)(((l)>> 8)&0xff),      \
 
235
                         *((c)++)=(unsigned char)(((l)    )&0xff),      \
 
236
                         l)
 
237
#endif
 
238
 
 
239
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
 
240
 
 
241
#ifndef PEDANTIC
 
242
# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
 
243
#  if defined(__s390x__)
 
244
#   define HOST_c2l(c,l)        ({ asm ("lrv    %0,0(%1)"               \
 
245
                                        :"=r"(l) : "r"(c));             \
 
246
                                   (c)+=4; (l);                         })
 
247
#   define HOST_l2c(l,c)        ({ asm ("strv   %0,0(%1)"               \
 
248
                                        : : "r"(l),"r"(c) : "memory");  \
 
249
                                   (c)+=4; (l);                         })
 
250
#  endif
 
251
# endif
 
252
#endif
 
253
#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
 
254
# ifndef B_ENDIAN
 
255
   /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
 
256
#  define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l)
 
257
#  define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l)
 
258
# endif
 
259
#endif
 
260
 
 
261
#ifndef HOST_c2l
 
262
#define HOST_c2l(c,l)   (l =(((unsigned long)(*((c)++)))    ),          \
 
263
                         l|=(((unsigned long)(*((c)++)))<< 8),          \
 
264
                         l|=(((unsigned long)(*((c)++)))<<16),          \
 
265
                         l|=(((unsigned long)(*((c)++)))<<24),          \
 
266
                         l)
 
267
#endif
 
268
#ifndef HOST_l2c
 
269
#define HOST_l2c(l,c)   (*((c)++)=(unsigned char)(((l)    )&0xff),      \
 
270
                         *((c)++)=(unsigned char)(((l)>> 8)&0xff),      \
 
271
                         *((c)++)=(unsigned char)(((l)>>16)&0xff),      \
 
272
                         *((c)++)=(unsigned char)(((l)>>24)&0xff),      \
 
273
                         l)
 
274
#endif
 
275
 
 
276
#endif
 
277
 
 
278
/*
 
279
 * Time for some action:-)
 
280
 */
 
281
 
 
282
int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
 
283
        {
 
284
        const unsigned char *data=data_;
 
285
        unsigned char *p;
 
286
        HASH_LONG l;
 
287
        size_t n;
 
288
 
 
289
        if (len==0) return 1;
 
290
 
 
291
        l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL;
 
292
        /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
 
293
         * Wei Dai <weidai@eskimo.com> for pointing it out. */
 
294
        if (l < c->Nl) /* overflow */
 
295
                c->Nh++;
 
296
        c->Nh+=(len>>29);       /* might cause compiler warning on 16-bit */
 
297
        c->Nl=l;
 
298
 
 
299
        n = c->num;
 
300
        if (n != 0)
 
301
                {
 
302
                p=(unsigned char *)c->data;
 
303
 
 
304
                if ((n+len) >= HASH_CBLOCK)
 
305
                        {
 
306
                        memcpy (p+n,data,HASH_CBLOCK-n);
 
307
                        HASH_BLOCK_DATA_ORDER (c,p,1);
 
308
                        n      = HASH_CBLOCK-n;
 
309
                        data  += n;
 
310
                        len   -= n;
 
311
                        c->num = 0;
 
312
                        memset (p,0,HASH_CBLOCK);       /* keep it zeroed */
 
313
                        }
 
314
                else
 
315
                        {
 
316
                        memcpy (p+n,data,len);
 
317
                        c->num += (unsigned int)len;
 
318
                        return 1;
 
319
                        }
 
320
                }
 
321
 
 
322
        n = len/HASH_CBLOCK;
 
323
        if (n > 0)
 
324
                {
 
325
                HASH_BLOCK_DATA_ORDER (c,data,n);
 
326
                n    *= HASH_CBLOCK;
 
327
                data += n;
 
328
                len  -= n;
 
329
                }
 
330
 
 
331
        if (len != 0)
 
332
                {
 
333
                p = (unsigned char *)c->data;
 
334
                c->num = len;
 
335
                memcpy (p,data,len);
 
336
                }
 
337
        return 1;
 
338
        }
 
339
 
 
340
 
 
341
void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
 
342
        {
 
343
        HASH_BLOCK_DATA_ORDER (c,data,1);
 
344
        }
 
345
 
 
346
 
 
347
int HASH_FINAL (unsigned char *md, HASH_CTX *c)
 
348
        {
 
349
        unsigned char *p = (unsigned char *)c->data;
 
350
        size_t n = c->num;
 
351
 
 
352
        p[n] = 0x80; /* there is always room for one */
 
353
        n++;
 
354
 
 
355
        if (n > (HASH_CBLOCK-8))
 
356
                {
 
357
                memset (p+n,0,HASH_CBLOCK-n);
 
358
                n=0;
 
359
                HASH_BLOCK_DATA_ORDER (c,p,1);
 
360
                }
 
361
        memset (p+n,0,HASH_CBLOCK-8-n);
 
362
 
 
363
        p += HASH_CBLOCK-8;
 
364
#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
 
365
        (void)HOST_l2c(c->Nh,p);
 
366
        (void)HOST_l2c(c->Nl,p);
 
367
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
 
368
        (void)HOST_l2c(c->Nl,p);
 
369
        (void)HOST_l2c(c->Nh,p);
 
370
#endif
 
371
        p -= HASH_CBLOCK;
 
372
        HASH_BLOCK_DATA_ORDER (c,p,1);
 
373
        c->num=0;
 
374
        memset (p,0,HASH_CBLOCK);
 
375
 
 
376
#ifndef HASH_MAKE_STRING
 
377
#error "HASH_MAKE_STRING must be defined!"
 
378
#else
 
379
        HASH_MAKE_STRING(c,md);
 
380
#endif
 
381
 
 
382
        return 1;
 
383
        }
 
384
 
 
385
#ifndef MD32_REG_T
 
386
#define MD32_REG_T long
 
387
/*
 
388
 * This comment was originaly written for MD5, which is why it
 
389
 * discusses A-D. But it basically applies to all 32-bit digests,
 
390
 * which is why it was moved to common header file.
 
391
 *
 
392
 * In case you wonder why A-D are declared as long and not
 
393
 * as MD5_LONG. Doing so results in slight performance
 
394
 * boost on LP64 architectures. The catch is we don't
 
395
 * really care if 32 MSBs of a 64-bit register get polluted
 
396
 * with eventual overflows as we *save* only 32 LSBs in
 
397
 * *either* case. Now declaring 'em long excuses the compiler
 
398
 * from keeping 32 MSBs zeroed resulting in 13% performance
 
399
 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
 
400
 * Well, to be honest it should say that this *prevents* 
 
401
 * performance degradation.
 
402
 *                              <appro@fy.chalmers.se>
 
403
 * Apparently there're LP64 compilers that generate better
 
404
 * code if A-D are declared int. Most notably GCC-x86_64
 
405
 * generates better code.
 
406
 *                              <appro@fy.chalmers.se>
 
407
 */
 
408
#endif