【发布时间】:2014-10-06 16:36:55
【问题描述】:
请告诉我,如何检查 OpenSSL 是否支持/使用 Intel AES-NI?
【问题讨论】:
请告诉我,如何检查 OpenSSL 是否支持/使用 Intel AES-NI?
【问题讨论】:
如何检查 OpenSSL 是否支持/使用 Intel AES-NI?
它不是那么简单,虽然它应该是。 OpenSSL 曾经提供一个函数来获取为 ia32 处理器检测到的功能,但它不再可用。请参阅OPENSSL_ia32cap man page 中对OPENSSL_ia32cap_loc 的讨论。另请参阅 OpenSSL 邮件列表中的 Verify AES-NI use at runtime?。
如果您正在链接到 OpenSSL 静态库,那么您可以使用:
extern unsigned int OPENSSL_ia32cap_P[];
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
if(AESNI_CAPABLE)
/* AES-NI is available */
如果您正在链接到 OpenSSL 共享对象,则符号 OPENSSL_ia32cap_P 将不导出。在这种情况下,您需要编写自己的检测代码。
我什至不关心 OpenSSL,因为它只适用于库的静态链接。我在下面分享了我用于检测的代码。我相信我从英特尔的 Dave Johnston(他设计了 RDRAND 电路)那里抄袭了很大一部分。
注意:下面的代码可能会错误地拒绝AMD processor with AES-NI。我没有要测试的处理器,所以我不能提供代码。
注意:下面的代码在 Valgrind 下不会按预期执行。 AES-NI 或 RDRAND 指令没有仿真,因此 Valgrind 从CPUID 返回一个“篡改”值,因此它们似乎不可用。请参阅邮件列表中的Incorrect results from inline assembly when running under Valgrind。
即使 AES-NI 可用,它确实不意味着您将要使用它。
如果您使用像 AES_* 这样的低级原语,那么您将不使用 AES-NI,因为它是一种软件实现。
如果您使用高级EVP_* 齿轮,那么您将使用AES-NI(如果可用)。库将自动切换到 AES-NI。
如果 AES-NI 可用但您不想使用它,则在启动程序之前执行以下操作:
$ export OPENSSL_ia32cap="~0x200000200000000"
您可以使用以下 OpenSSL 命令测试速度差异。切换上面的导出以查看差异:
$ 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)
);
}
【讨论】:
unset OPENSSL_ia32cap。
根据jww 提供的信息构建了一对快速单线:
openssl speed -elapsed -evp aes-128-cbc ... OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc ...第一行的输出应该明显快于第二行。在我的 i5 测试机上,几乎翻了一番。
【讨论】: