Tell me please, how can I check if OpenSSL is support/use the Intel AES-NI?
问题:
回答1:
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
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 EAX), "=b"(info->EBX), "=c"(info->ECX), "=d"(info->EDX) : "a"(func), "c"(subfunc) ); }
回答2:
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.