enable - ¿Cómo puedo verificar si OpenSSL es compatible/usa Intel AES-NI?
vt-d (2)
¿Cómo puedo verificar si OpenSSL es compatible / use Intel AES-NI?
No es tan simple, aunque debería ser. OpenSSL solía proporcionar una función para obtener las capacidades detectadas para un procesador ia32, pero ya no está disponible. Consulte la discusión sobre OPENSSL_ia32cap_loc
en la página del manual OPENSSL_ia32cap
. También vea ¿ Verificar el uso de AES-NI en tiempo de ejecución? en la lista de correo de OpenSSL.
Si está enlazando a la biblioteca estática de OpenSSL, puede usar:
extern unsigned int OPENSSL_ia32cap_P[];
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
if(AESNI_CAPABLE)
/* AES-NI is available */
Si está enlazando al objeto compartido de OpenSSL, entonces el símbolo OPENSSL_ia32cap_P
no se exporta. En este caso, debe escribir su propio código de detección.
Ni siquiera me molesto con OpenSSL ya que solo funciona con enlaces estáticos de la biblioteca. Compartí el código que uso para la detección a continuación. Creo que arranqué una parte significativa de Dave Johnston de Intel (diseñó el circuito RDRAND).
Nota : el siguiente código podría rechazar incorrectamente un procesador AMD con AES-NI . No tengo un procesador para probar, así que no puedo ofrecer el código.
Nota : el código siguiente no funcionará como se espera en Valgrind. No hay emulación para las instrucciones AES-NI o RDRAND, por lo que Valgrind devuelve un valor "adulterado" de CPUID
para que parezca que no están disponibles. Consulte Resultados incorrectos del ensamblaje en línea cuando se ejecuta en Valgrind en la lista de correo.
Aunque AES-NI está disponible, no significa que va a usarlo.
Si usa las primitivas de bajo nivel como AES_*
, entonces no usará AES-NI porque es una implementación de software.
Si usa el equipo EVP_*
alto nivel, entonces usará AES-NI si está disponible. La biblioteca cambiará a AES-NI automáticamente.
Si AES-NI está disponible pero no desea usarlo, realice lo siguiente antes de iniciar su programa:
$ export OPENSSL_ia32cap="~0x200000200000000"
Puede probar la diferencia de velocidad con el siguiente comando OpenSSL. Alternar la exportación de arriba para ver las diferencias:
$ 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)
);
}
Dime, por favor, ¿cómo puedo verificar si OpenSSL es compatible / usar Intel AES-NI?
Un par de frases rápidas construidas a partir de la información proporcionada por jww :
openssl speed -elapsed -evp aes-128-cbc ... OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc ...
La salida de la primera línea debe ser significativamente más rápida que la segunda. En mi caso en una máquina de prueba i5, casi el doble.