Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if OpenSSL is support/use the Intel AES-NI?

Tags:

openssl

aes

Tell me please, how can I check if OpenSSL is support/use the Intel AES-NI?

like image 366
niXman Avatar asked Aug 13 '14 10:08

niXman


People also ask

How do I check my AES-NI support?

Look in /proc/cpuinfo . If you have the aes flag then your CPU has AES support.

Does OpenSSL support AES-NI?

You can see that AES speed with AES-NI acceleration is about five times higher than non-acceleration. This confirms that AES-NI is enabled for OpenSSL.

How do I enable AES-NI?

From the System Utilities screen, select System Configuration > BIOS/Platform Configuration (RBSU) > Server Security > Processor AES-NI Support and press Enter. Select a setting and press Enter. Enabled—Enables AES-NI support.

What is AES-NI support?

Use this option to enable or disable the Advanced Encryption Standard Instruction Set in the processor.


2 Answers

how can I check if OpenSSL is support/use the Intel AES-NI?

Its not that simple, though it should be. OpenSSL used to provide a function to get the capabilities detected for an ia32 processor, but its no longer available. See the discussion of OPENSSL_ia32cap_loc in the OPENSSL_ia32cap man page. Also see Verify AES-NI use at runtime? on the OpenSSL mailing list.

If you are linking to the OpenSSL static library, then you can use:

extern unsigned int OPENSSL_ia32cap_P[];
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))

if(AESNI_CAPABLE)
    /* AES-NI is available */

If you are linking to the OpenSSL shared object, then the symbol OPENSSL_ia32cap_P is not exported. In this case, you need to write your own detection code.

I don't even bother with OpenSSL since it only works with static linking of the library. I shared the code I use for detection below. I believe I ripped a significant portion of it from Dave Johnston of Intel (he designed the RDRAND circuit).

Note: the code below could incorrectly reject an AMD processor with AES-NI. I don't have a processor to test on, so I can't offer the code.

Note: the code below will not perform as expected under Valgrind. There's no emulation for the AES-NI or RDRAND instructions, so Valgrind returns a "doctored" value from CPUID so it appears they are not available. See Incorrect results from inline assembly when running under Valgrind on the mailing list.


Even though AES-NI is available, it does not mean you are going to use it.

If you use the low level primitives like AES_*, then you will not use AES-NI because its a software implementation.

If you use the high level EVP_* gear, then you will use AES-NI if its available. The library will switch to AES-NI automatically.


If AES-NI is available but you don't want to use it, then perform the following before launching you program:

$ export OPENSSL_ia32cap="~0x200000200000000"

You can test the speed difference with the following OpenSSL command. Toggle the export above to see the differences:

$ openssl speed -elapsed -evp aes-128-ecb

struct CPUIDinfo {
    unsigned int EAX;
    unsigned int EBX;
    unsigned int ECX;
    unsigned int EDX;
};

int HasIntelCpu();
int HasAESNI();
int HasRDRAND();

void cpuid_info(CPUIDinfo *info, const unsigned int func,
        const unsigned int subfunc);

int HasIntelCpu() {
    CPUIDinfo info;
    cpuid_info(&info, 0, 0);
    if (memcmp((char *) (&info.EBX), "Genu", 4) == 0
            && memcmp((char *) (&info.EDX), "ineI", 4) == 0
            && memcmp((char *) (&info.ECX), "ntel", 4) == 0) {

        return 1;
    }

    return 0;
}

int HasAESNI() {
    if (!HasIntelCpu())
        return 0;

    CPUIDinfo info;
    cpuid_info(&info, 1, 0);

    static const unsigned int AESNI_FLAG = (1 << 25);
    if ((info.ECX & AESNI_FLAG) == AESNI_FLAG)
        return 1;

    return 0;
}

int HasRDRAND() {

    if (!HasIntelCpu())
        return 0;

    CPUIDinfo info;
    cpuid_info(&info, 1, 0);

    static const unsigned int RDRAND_FLAG = (1 << 30);
    if ((info.ECX & RDRAND_FLAG) == RDRAND_FLAG)
        return 1;

    return 0;
}

void cpuid_info(CPUIDinfo *info, unsigned int func, unsigned int subfunc) {
    __asm__ __volatile__ (
            "cpuid"
            : "=a"(info->EAX), "=b"(info->EBX), "=c"(info->ECX), "=d"(info->EDX)
            : "a"(func), "c"(subfunc)
    );
}
like image 136
jww Avatar answered Nov 23 '22 06:11

jww


A couple quick one liners built from the information provided by jww:

openssl speed -elapsed -evp aes-128-cbc
...
OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc
...

Output of the first line should be significantly faster than the second. In my case on a i5 test machine, nearly double.

like image 33
NuSkooler Avatar answered Nov 23 '22 05:11

NuSkooler