Hi,

In CVS OPENSSL_1_0_1-stable branch, on a ILP32 target (where
sizeof(long) == 4), the function OPENSSL_ia32cap_loc() is clearing
upper bits of capability vector which disable support for SSE3, AES-NI,
etc...

See http://www.openssl.org/docs/crypto/OPENSSL_ia32cap.html for more
information.

In crypto/crypto.h:

unsigned long *OPENSSL_ia32cap_loc(void);
#define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))

In crypto/cryptlib.c:

unsigned int  OPENSSL_ia32cap_P[2];
unsigned long *OPENSSL_ia32cap_loc(void)
{   if (sizeof(long)==4)
        /*
         * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
         * clear second element to maintain the illusion that vector
         * is 32-bit.
         */
        OPENSSL_ia32cap_P[1]=0;
    return (unsigned long *)OPENSSL_ia32cap_P;
}

A user program not reading/writing OPENSSL_ia32cap before using other
encryption, decryption or digest functions would benefit from SSE3,
AES-NI and such if available. But after calling the function, those
support would be disabled.

In CVS HEAD, the problem does not exist. OPENSSL_ia32cap_loc() returns a
pointer to int instead of a pointer to long (this is an ABI change
between 1.0.1 and HEAD), and doesn't clear upper bits.

In crypto/crypto.h:

unsigned int *OPENSSL_ia32cap_loc(void);
#define OPENSSL_ia32cap ((OPENSSL_ia32cap_loc())[0])

In crypto/cryptlib.c:

extern unsigned int  OPENSSL_ia32cap_P[2];
unsigned int *OPENSSL_ia32cap_loc(void) { return OPENSSL_ia32cap_P; }

The solution currently in HEAD is not perfect since it doesn't allow
user program to read upper bits of the capability vector. Worse, it
doesn't allow it to write upper bits of the vector, for example to
disable some capabilities.

I think that a better way to expose capabilities to user program would
be an array and a count/length:

In crypto/crypto.h:

extern unsigned int *OPENSSL_ia32cap_loc(void);
#define OPENSSL_ia32cap (OPENSSL_ia32cap_loc())

extern unsigned int OPENSSL_ia32cap_cnt(void);
#define OPENSSL_ia32cap_cnt (OPENSSL_ia32cap_cnt())

In crypto/cryptlib.c:

#define OPENSSL_ia32cap_CNT 2

extern unsigned int OPENSSL_ia32cap_P[OPENSSL_ia32cap_CNT];
unsigned int *OPENSSL_ia32cap_loc(void) { return OPENSSL_ia32cap_P; }
unsigned int OPENSSL_ia32cap_cnt(void) { return OPENSSL_ia32cap_CNT; }

Regards

-- 
Yann Droneaud


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [email protected]

Reply via email to