155714Skris/* crypto/md32_common.h */
255714Skris/* ====================================================================
3194206Ssimon * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
455714Skris *
555714Skris * Redistribution and use in source and binary forms, with or without
655714Skris * modification, are permitted provided that the following conditions
755714Skris * are met:
855714Skris *
955714Skris * 1. Redistributions of source code must retain the above copyright
10280304Sjkim *    notice, this list of conditions and the following disclaimer.
1155714Skris *
1255714Skris * 2. Redistributions in binary form must reproduce the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer in
1455714Skris *    the documentation and/or other materials provided with the
1555714Skris *    distribution.
1655714Skris *
1755714Skris * 3. All advertising materials mentioning features or use of this
1855714Skris *    software must display the following acknowledgment:
1955714Skris *    "This product includes software developed by the OpenSSL Project
2055714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2155714Skris *
2255714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2355714Skris *    endorse or promote products derived from this software without
2455714Skris *    prior written permission. For written permission, please contact
2555714Skris *    licensing@OpenSSL.org.
2655714Skris *
2755714Skris * 5. Products derived from this software may not be called "OpenSSL"
2855714Skris *    nor may "OpenSSL" appear in their names without prior written
2955714Skris *    permission of the OpenSSL Project.
3055714Skris *
3155714Skris * 6. Redistributions of any form whatsoever must retain the following
3255714Skris *    acknowledgment:
3355714Skris *    "This product includes software developed by the OpenSSL Project
3455714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3555714Skris *
3655714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
3755714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3855714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3955714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4055714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4155714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4255714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4355714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4455714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4555714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4655714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4755714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
4855714Skris * ====================================================================
4955714Skris *
5055714Skris */
5155714Skris
52280304Sjkim/*-
5355714Skris * This is a generic 32 bit "collector" for message digest algorithms.
5455714Skris * Whenever needed it collects input character stream into chunks of
5555714Skris * 32 bit values and invokes a block function that performs actual hash
5655714Skris * calculations.
5755714Skris *
5855714Skris * Porting guide.
5955714Skris *
6055714Skris * Obligatory macros:
6155714Skris *
6255714Skris * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
63280304Sjkim *      this macro defines byte order of input stream.
6455714Skris * HASH_CBLOCK
65280304Sjkim *      size of a unit chunk HASH_BLOCK operates on.
6655714Skris * HASH_LONG
67280304Sjkim *      has to be at lest 32 bit wide, if it's wider, then
68280304Sjkim *      HASH_LONG_LOG2 *has to* be defined along
6955714Skris * HASH_CTX
70280304Sjkim *      context structure that at least contains following
71280304Sjkim *      members:
72280304Sjkim *              typedef struct {
73280304Sjkim *                      ...
74280304Sjkim *                      HASH_LONG       Nl,Nh;
75280304Sjkim *                      either {
76280304Sjkim *                      HASH_LONG       data[HASH_LBLOCK];
77280304Sjkim *                      unsigned char   data[HASH_CBLOCK];
78280304Sjkim *                      };
79280304Sjkim *                      unsigned int    num;
80280304Sjkim *                      ...
81280304Sjkim *                      } HASH_CTX;
82280304Sjkim *      data[] vector is expected to be zeroed upon first call to
83280304Sjkim *      HASH_UPDATE.
8455714Skris * HASH_UPDATE
85280304Sjkim *      name of "Update" function, implemented here.
8655714Skris * HASH_TRANSFORM
87280304Sjkim *      name of "Transform" function, implemented here.
8855714Skris * HASH_FINAL
89280304Sjkim *      name of "Final" function, implemented here.
9055714Skris * HASH_BLOCK_DATA_ORDER
91280304Sjkim *      name of "block" function capable of treating *unaligned* input
92280304Sjkim *      message in original (data) byte order, implemented externally.
9359191Skris * HASH_MAKE_STRING
94280304Sjkim *      macro convering context variables to an ASCII hash string.
9555714Skris *
9655714Skris * MD5 example:
9755714Skris *
98280304Sjkim *      #define DATA_ORDER_IS_LITTLE_ENDIAN
9955714Skris *
100280304Sjkim *      #define HASH_LONG               MD5_LONG
101280304Sjkim *      #define HASH_LONG_LOG2          MD5_LONG_LOG2
102280304Sjkim *      #define HASH_CTX                MD5_CTX
103280304Sjkim *      #define HASH_CBLOCK             MD5_CBLOCK
104280304Sjkim *      #define HASH_UPDATE             MD5_Update
105280304Sjkim *      #define HASH_TRANSFORM          MD5_Transform
106280304Sjkim *      #define HASH_FINAL              MD5_Final
107280304Sjkim *      #define HASH_BLOCK_DATA_ORDER   md5_block_data_order
10855714Skris *
109280304Sjkim *                                      <appro@fy.chalmers.se>
11055714Skris */
11155714Skris
11255714Skris#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
113280304Sjkim# error "DATA_ORDER must be defined!"
11455714Skris#endif
11555714Skris
11655714Skris#ifndef HASH_CBLOCK
117280304Sjkim# error "HASH_CBLOCK must be defined!"
11855714Skris#endif
11955714Skris#ifndef HASH_LONG
120280304Sjkim# error "HASH_LONG must be defined!"
12155714Skris#endif
12255714Skris#ifndef HASH_CTX
123280304Sjkim# error "HASH_CTX must be defined!"
12455714Skris#endif
12555714Skris
12655714Skris#ifndef HASH_UPDATE
127280304Sjkim# error "HASH_UPDATE must be defined!"
12855714Skris#endif
12955714Skris#ifndef HASH_TRANSFORM
130280304Sjkim# error "HASH_TRANSFORM must be defined!"
13155714Skris#endif
13255714Skris#ifndef HASH_FINAL
133280304Sjkim# error "HASH_FINAL must be defined!"
13455714Skris#endif
13555714Skris
13655714Skris#ifndef HASH_BLOCK_DATA_ORDER
137280304Sjkim# error "HASH_BLOCK_DATA_ORDER must be defined!"
13855714Skris#endif
13955714Skris
14055714Skris/*
14155714Skris * Engage compiler specific rotate intrinsic function if available.
14255714Skris */
14355714Skris#undef ROTATE
14455714Skris#ifndef PEDANTIC
145284285Sjkim# if defined(_MSC_VER)
146280304Sjkim#  define ROTATE(a,n)   _lrotl(a,n)
147284285Sjkim# elif defined(__ICC)
148284285Sjkim#  define ROTATE(a,n)   _rotl(a,n)
14959191Skris# elif defined(__MWERKS__)
15059191Skris#  if defined(__POWERPC__)
151280304Sjkim#   define ROTATE(a,n)  __rlwinm(a,n,0,31)
15259191Skris#  elif defined(__MC68K__)
15359191Skris    /* Motorola specific tweak. <appro@fy.chalmers.se> */
154280304Sjkim#   define ROTATE(a,n)  ( n<24 ? __rol(a,n) : __ror(a,32-n) )
15559191Skris#  else
156280304Sjkim#   define ROTATE(a,n)  __rol(a,n)
15759191Skris#  endif
158109998Smarkm# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
15955714Skris  /*
16055714Skris   * Some GNU C inline assembler templates. Note that these are
16155714Skris   * rotates by *constant* number of bits! But that's exactly
16255714Skris   * what we need here...
163280304Sjkim   *                                    <appro@fy.chalmers.se>
16455714Skris   */
165109998Smarkm#  if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
166280304Sjkim#   define ROTATE(a,n)  ({ register unsigned int ret;   \
167280304Sjkim                                asm (                   \
168280304Sjkim                                "roll %1,%0"            \
169280304Sjkim                                : "=r"(ret)             \
170280304Sjkim                                : "I"(n), "0"((unsigned int)(a))        \
171280304Sjkim                                : "cc");                \
172280304Sjkim                           ret;                         \
173280304Sjkim                        })
174194206Ssimon#  elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
175280304Sjkim        defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
176280304Sjkim#   define ROTATE(a,n)  ({ register unsigned int ret;   \
177280304Sjkim                                asm (                   \
178280304Sjkim                                "rlwinm %0,%1,%2,0,31"  \
179280304Sjkim                                : "=r"(ret)             \
180280304Sjkim                                : "r"(a), "I"(n));      \
181280304Sjkim                           ret;                         \
182280304Sjkim                        })
183194206Ssimon#  elif defined(__s390x__)
184280304Sjkim#   define ROTATE(a,n) ({ register unsigned int ret;    \
185280304Sjkim                                asm ("rll %0,%1,%2"     \
186280304Sjkim                                : "=r"(ret)             \
187280304Sjkim                                : "r"(a), "I"(n));      \
188280304Sjkim                          ret;                          \
189280304Sjkim                        })
19055714Skris#  endif
19155714Skris# endif
192280304Sjkim#endif                          /* PEDANTIC */
19355714Skris
19455714Skris#ifndef ROTATE
195280304Sjkim# define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
19655714Skris#endif
19755714Skris
19855714Skris#if defined(DATA_ORDER_IS_BIG_ENDIAN)
19955714Skris
200280304Sjkim# ifndef PEDANTIC
201280304Sjkim#  if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
202280304Sjkim#   if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
203160814Ssimon      (defined(__x86_64) || defined(__x86_64__))
204280304Sjkim#    if !defined(B_ENDIAN)
205160814Ssimon    /*
206160814Ssimon     * This gives ~30-40% performance improvement in SHA-256 compiled
207160814Ssimon     * with gcc [on P4]. Well, first macro to be frank. We can pull
208160814Ssimon     * this trick on x86* platforms only, because these CPUs can fetch
209160814Ssimon     * unaligned data without raising an exception.
210160814Ssimon     */
211280304Sjkim#     define HOST_c2l(c,l)        ({ unsigned int r=*((const unsigned int *)(c)); \
212280304Sjkim                                   asm ("bswapl %0":"=r"(r):"0"(r));    \
213280304Sjkim                                   (c)+=4; (l)=r;                       })
214280304Sjkim#     define HOST_l2c(l,c)        ({ unsigned int r=(l);                  \
215280304Sjkim                                   asm ("bswapl %0":"=r"(r):"0"(r));    \
216280304Sjkim                                   *((unsigned int *)(c))=r; (c)+=4; r; })
217280304Sjkim#    endif
218194206Ssimon#   endif
219160814Ssimon#  endif
220160814Ssimon# endif
221280304Sjkim# if defined(__s390__) || defined(__s390x__)
222280304Sjkim#  define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
223280304Sjkim#  define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
224280304Sjkim# endif
225160814Ssimon
226280304Sjkim# ifndef HOST_c2l
227280304Sjkim#  define HOST_c2l(c,l)   (l =(((unsigned long)(*((c)++)))<<24),          \
228280304Sjkim                         l|=(((unsigned long)(*((c)++)))<<16),          \
229280304Sjkim                         l|=(((unsigned long)(*((c)++)))<< 8),          \
230280304Sjkim                         l|=(((unsigned long)(*((c)++)))    )           )
231280304Sjkim# endif
232280304Sjkim# ifndef HOST_l2c
233280304Sjkim#  define HOST_l2c(l,c)   (*((c)++)=(unsigned char)(((l)>>24)&0xff),      \
234280304Sjkim                         *((c)++)=(unsigned char)(((l)>>16)&0xff),      \
235280304Sjkim                         *((c)++)=(unsigned char)(((l)>> 8)&0xff),      \
236280304Sjkim                         *((c)++)=(unsigned char)(((l)    )&0xff),      \
237280304Sjkim                         l)
238280304Sjkim# endif
23955714Skris
24055714Skris#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
24155714Skris
242280304Sjkim# ifndef PEDANTIC
243280304Sjkim#  if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
244280304Sjkim#   if defined(__s390x__)
245280304Sjkim#    define HOST_c2l(c,l)        ({ asm ("lrv    %0,%1"                  \
246280304Sjkim                                   :"=d"(l) :"m"(*(const unsigned int *)(c)));\
247280304Sjkim                                   (c)+=4; (l);                         })
248280304Sjkim#    define HOST_l2c(l,c)        ({ asm ("strv   %1,%0"                  \
249280304Sjkim                                   :"=m"(*(unsigned int *)(c)) :"d"(l));\
250280304Sjkim                                   (c)+=4; (l);                         })
251280304Sjkim#   endif
252194206Ssimon#  endif
253194206Ssimon# endif
254280304Sjkim# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
255280304Sjkim#  ifndef B_ENDIAN
256160814Ssimon   /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
257280304Sjkim#   define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l)
258280304Sjkim#   define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l)
259280304Sjkim#  endif
260160814Ssimon# endif
261160814Ssimon
262280304Sjkim# ifndef HOST_c2l
263280304Sjkim#  define HOST_c2l(c,l)   (l =(((unsigned long)(*((c)++)))    ),          \
264280304Sjkim                         l|=(((unsigned long)(*((c)++)))<< 8),          \
265280304Sjkim                         l|=(((unsigned long)(*((c)++)))<<16),          \
266280304Sjkim                         l|=(((unsigned long)(*((c)++)))<<24)           )
267280304Sjkim# endif
268280304Sjkim# ifndef HOST_l2c
269280304Sjkim#  define HOST_l2c(l,c)   (*((c)++)=(unsigned char)(((l)    )&0xff),      \
270280304Sjkim                         *((c)++)=(unsigned char)(((l)>> 8)&0xff),      \
271280304Sjkim                         *((c)++)=(unsigned char)(((l)>>16)&0xff),      \
272280304Sjkim                         *((c)++)=(unsigned char)(((l)>>24)&0xff),      \
273280304Sjkim                         l)
274280304Sjkim# endif
27555714Skris
27655714Skris#endif
27755714Skris
27855714Skris/*
27955714Skris * Time for some action:-)
28055714Skris */
28155714Skris
282280304Sjkimint HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
283280304Sjkim{
284280304Sjkim    const unsigned char *data = data_;
285280304Sjkim    unsigned char *p;
286280304Sjkim    HASH_LONG l;
287280304Sjkim    size_t n;
28855714Skris
289280304Sjkim    if (len == 0)
290280304Sjkim        return 1;
29155714Skris
292280304Sjkim    l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL;
293280304Sjkim    /*
294280304Sjkim     * 95-05-24 eay Fixed a bug with the overflow handling, thanks to Wei Dai
295280304Sjkim     * <weidai@eskimo.com> for pointing it out.
296280304Sjkim     */
297280304Sjkim    if (l < c->Nl)              /* overflow */
298280304Sjkim        c->Nh++;
299280304Sjkim    c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on
300280304Sjkim                                       * 16-bit */
301280304Sjkim    c->Nl = l;
30255714Skris
303280304Sjkim    n = c->num;
304280304Sjkim    if (n != 0) {
305280304Sjkim        p = (unsigned char *)c->data;
30655714Skris
307280304Sjkim        if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
308280304Sjkim            memcpy(p + n, data, HASH_CBLOCK - n);
309280304Sjkim            HASH_BLOCK_DATA_ORDER(c, p, 1);
310280304Sjkim            n = HASH_CBLOCK - n;
311280304Sjkim            data += n;
312280304Sjkim            len -= n;
313280304Sjkim            c->num = 0;
314280304Sjkim            memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
315280304Sjkim        } else {
316280304Sjkim            memcpy(p + n, data, len);
317280304Sjkim            c->num += (unsigned int)len;
318280304Sjkim            return 1;
319280304Sjkim        }
320280304Sjkim    }
32155714Skris
322280304Sjkim    n = len / HASH_CBLOCK;
323280304Sjkim    if (n > 0) {
324280304Sjkim        HASH_BLOCK_DATA_ORDER(c, data, n);
325280304Sjkim        n *= HASH_CBLOCK;
326280304Sjkim        data += n;
327280304Sjkim        len -= n;
328280304Sjkim    }
32955714Skris
330280304Sjkim    if (len != 0) {
331280304Sjkim        p = (unsigned char *)c->data;
332280304Sjkim        c->num = (unsigned int)len;
333280304Sjkim        memcpy(p, data, len);
334280304Sjkim    }
335280304Sjkim    return 1;
336280304Sjkim}
33755714Skris
338280304Sjkimvoid HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data)
339280304Sjkim{
340280304Sjkim    HASH_BLOCK_DATA_ORDER(c, data, 1);
341280304Sjkim}
34255714Skris
343280304Sjkimint HASH_FINAL(unsigned char *md, HASH_CTX *c)
344280304Sjkim{
345280304Sjkim    unsigned char *p = (unsigned char *)c->data;
346280304Sjkim    size_t n = c->num;
34755714Skris
348280304Sjkim    p[n] = 0x80;                /* there is always room for one */
349280304Sjkim    n++;
35055714Skris
351280304Sjkim    if (n > (HASH_CBLOCK - 8)) {
352280304Sjkim        memset(p + n, 0, HASH_CBLOCK - n);
353280304Sjkim        n = 0;
354280304Sjkim        HASH_BLOCK_DATA_ORDER(c, p, 1);
355280304Sjkim    }
356280304Sjkim    memset(p + n, 0, HASH_CBLOCK - 8 - n);
35755714Skris
358280304Sjkim    p += HASH_CBLOCK - 8;
35955714Skris#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
360280304Sjkim    (void)HOST_l2c(c->Nh, p);
361280304Sjkim    (void)HOST_l2c(c->Nl, p);
36255714Skris#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
363280304Sjkim    (void)HOST_l2c(c->Nl, p);
364280304Sjkim    (void)HOST_l2c(c->Nh, p);
36555714Skris#endif
366280304Sjkim    p -= HASH_CBLOCK;
367280304Sjkim    HASH_BLOCK_DATA_ORDER(c, p, 1);
368280304Sjkim    c->num = 0;
369280304Sjkim    memset(p, 0, HASH_CBLOCK);
37055714Skris
37159191Skris#ifndef HASH_MAKE_STRING
372280304Sjkim# error "HASH_MAKE_STRING must be defined!"
37359191Skris#else
374280304Sjkim    HASH_MAKE_STRING(c, md);
37559191Skris#endif
37655714Skris
377280304Sjkim    return 1;
378280304Sjkim}
379109998Smarkm
380109998Smarkm#ifndef MD32_REG_T
381280304Sjkim# if defined(__alpha) || defined(__sparcv9) || defined(__mips)
382280304Sjkim#  define MD32_REG_T long
383109998Smarkm/*
384109998Smarkm * This comment was originaly written for MD5, which is why it
385109998Smarkm * discusses A-D. But it basically applies to all 32-bit digests,
386109998Smarkm * which is why it was moved to common header file.
387109998Smarkm *
388109998Smarkm * In case you wonder why A-D are declared as long and not
389109998Smarkm * as MD5_LONG. Doing so results in slight performance
390109998Smarkm * boost on LP64 architectures. The catch is we don't
391109998Smarkm * really care if 32 MSBs of a 64-bit register get polluted
392109998Smarkm * with eventual overflows as we *save* only 32 LSBs in
393109998Smarkm * *either* case. Now declaring 'em long excuses the compiler
394109998Smarkm * from keeping 32 MSBs zeroed resulting in 13% performance
395109998Smarkm * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
396280304Sjkim * Well, to be honest it should say that this *prevents*
397109998Smarkm * performance degradation.
398280304Sjkim *                              <appro@fy.chalmers.se>
399212961Srpaulo */
400280304Sjkim# else
401212961Srpaulo/*
402212961Srpaulo * Above is not absolute and there are LP64 compilers that
403212961Srpaulo * generate better code if MD32_REG_T is defined int. The above
404212961Srpaulo * pre-processor condition reflects the circumstances under which
405212961Srpaulo * the conclusion was made and is subject to further extension.
406280304Sjkim *                              <appro@fy.chalmers.se>
407109998Smarkm */
408280304Sjkim#  define MD32_REG_T int
409280304Sjkim# endif
410109998Smarkm#endif
411