openssl generates incorrect sha/md5 value if built with icc compiler


Problem : 
    Build the openssl-0.9.8l application with icc, use command "./openssl sha ./test.dat" to generate the sha value for the empty file "test.dat", the icc build openssl reports different sha value compared to gcc build openssl. It's also the same for md5 hash value.

Environment : 
    icc version: 11.x
    gcc version: 4.x
    OS: Linux on Intel64 platform

Root Cause : 
    The issue is in the openssl application. It uses different ROTATE implementation for ICC and gcc, which induced the different result. In the file openssl-0.9.8l/crypto/md32_common.h
For ICC, it uses:
# define ROTATE(a,n) _lrotl(a,n)
For gcc, it uses:
# define ROTATE(a,n) ({ register unsigned int ret; asm ( "roll %1,%0" : "=r"(ret) : "I"(n), "0"(a) : "cc"); ret; })
The function declaration for _lrotl is defined in icc header file ia32intrin.h:
extern unsigned long __cdecl _lrotl(unsigned long, int)
On linux Intel64 platform, unsigned long is 64 bits size. However, in the gcc implementation, it uses "unsigned int" for the ROTATE result which is 32 bits size. Therefore, the return value is different for ICC and GCC.

Resolution : 
To workaround the issue, open the file openssl-0.9.8l/crypto/md32_common.h, go to line 145, change:
# if defined(_MSC_VER) || defined(__ICC)
to
# if defined(_MSC_VER) || defined(x_ICC)
that is, to disable the macro definition for ICC ROTATE. The icc build and gcc build will use the same RORATE definition. The sha or md5 hash value will be same for icc and gcc.


For more complete information about compiler optimizations, see our Optimization Notice.