evp: prevent underflow in base64 decoding
[openssl.git] / crypto / md32_common.h
index ce956df3825ac8bd5aad2d2567acb671ce3db596..bb7381952a2263dc9ee56afbf4af20dc33078001 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/md32_common.h */
 /* ====================================================================
- * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
                                asm (                   \
                                "roll %1,%0"            \
                                : "=r"(ret)             \
-                               : "I"(n), "0"(a)        \
+                               : "I"(n), "0"((unsigned int)(a))        \
                                : "cc");                \
                           ret;                         \
                        })
                                : "r"(a), "I"(n));      \
                           ret;                         \
                        })
+#  elif defined(__s390x__)
+#   define ROTATE(a,n) ({ register unsigned int ret;   \
+                               asm ("rll %0,%1,%2"     \
+                               : "=r"(ret)             \
+                               : "r"(a), "I"(n));      \
+                         ret;                          \
+                       })
 #  endif
 # endif
 #endif /* PEDANTIC */
 #  endif
 # endif
 #endif
+#if defined(__s390__) || defined(__s390x__)
+# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
+# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
+#endif
 
 #ifndef HOST_c2l
 #define HOST_c2l(c,l)  (l =(((unsigned long)(*((c)++)))<<24),          \
 
 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
 
+#ifndef PEDANTIC
+# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
+#  if defined(__s390x__)
+#   define HOST_c2l(c,l)       ({ asm ("lrv    %0,%1"                  \
+                                  :"=d"(l) :"m"(*(const unsigned int *)(c)));\
+                                  (c)+=4; (l);                         })
+#   define HOST_l2c(l,c)       ({ asm ("strv   %1,%0"                  \
+                                  :"=m"(*(unsigned int *)(c)) :"d"(l));\
+                                  (c)+=4; (l);                         })
+#  endif
+# endif
+#endif
 #if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
 # ifndef B_ENDIAN
    /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
@@ -270,7 +293,7 @@ int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
         * Wei Dai <weidai@eskimo.com> for pointing it out. */
        if (l < c->Nl) /* overflow */
                c->Nh++;
-       c->Nh+=(len>>29);       /* might cause compiler warning on 16-bit */
+       c->Nh+=(HASH_LONG)(len>>29);    /* might cause compiler warning on 16-bit */
        c->Nl=l;
 
        n = c->num;
@@ -278,7 +301,7 @@ int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
                {
                p=(unsigned char *)c->data;
 
-               if ((n+len) >= HASH_CBLOCK)
+               if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK)
                        {
                        memcpy (p+n,data,HASH_CBLOCK-n);
                        HASH_BLOCK_DATA_ORDER (c,p,1);
@@ -308,7 +331,7 @@ int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
        if (len != 0)
                {
                p = (unsigned char *)c->data;
-               c->num = len;
+               c->num = (unsigned int)len;
                memcpy (p,data,len);
                }
        return 1;
@@ -331,9 +354,11 @@ int HASH_FINAL (unsigned char *md, HASH_CTX *c)
 
        if (n > (HASH_CBLOCK-8))
                {
+               memset (p+n,0,HASH_CBLOCK-n);
+               n=0;
                HASH_BLOCK_DATA_ORDER (c,p,1);
-               memset (p,0,HASH_CBLOCK);
                }
+       memset (p+n,0,HASH_CBLOCK-8-n);
 
        p += HASH_CBLOCK-8;
 #if   defined(DATA_ORDER_IS_BIG_ENDIAN)
@@ -358,6 +383,7 @@ int HASH_FINAL (unsigned char *md, HASH_CTX *c)
        }
 
 #ifndef MD32_REG_T
+#if defined(__alpha) || defined(__sparcv9) || defined(__mips)
 #define MD32_REG_T long
 /*
  * This comment was originaly written for MD5, which is why it
@@ -375,9 +401,15 @@ int HASH_FINAL (unsigned char *md, HASH_CTX *c)
  * Well, to be honest it should say that this *prevents* 
  * performance degradation.
  *                             <appro@fy.chalmers.se>
- * Apparently there're LP64 compilers that generate better
- * code if A-D are declared int. Most notably GCC-x86_64
- * generates better code.
+ */
+#else
+/*
+ * Above is not absolute and there are LP64 compilers that
+ * generate better code if MD32_REG_T is defined int. The above
+ * pre-processor condition reflects the circumstances under which
+ * the conclusion was made and is subject to further extension.
  *                             <appro@fy.chalmers.se>
  */
+#define MD32_REG_T int
+#endif
 #endif