如何检查OpenSSL是否支持/使用Intel AES-NI?

请告诉我,如何检查OpenSSL是否支持/使用英特尔AES-NI?
最佳答案

how can I check if OpenSSL is support/use the 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_P.在这种情况下,您需要编写自己的检测码.

我甚至不打扰OpenSSL,因为它只适用于库的静态链接.我在下面分享了我用于检测的代码.我相信我从英特尔的戴夫·约翰斯顿(Dave Johnston)中挖出了很大一部分(他设计了RDRAND电路).

注意:下面的代码可能会错误地拒绝AMD processor with AES-NI.我没有处理器进行测试,所以我不能提供代码.

注意:以下代码将无法按照Va​​lgrind的预期执行.没有对AES-NI或RDRAND指令进行仿真,所以Valgrind从CPUID返回一个“doctored”值,因此它似乎不可用.请参阅邮件列表中的Incorrect results from inline assembly when running under Valgrind.

尽管AES-NI可用,但并不意味着您将使用它.

如果您使用像AES_ *这样的低级原语,那么您不会使用AES-NI,因为它是一个软件实现.

如果您使用高级EVP_ *齿轮,那么如果可用,则使用AES-NI.该库将自动切换到AES-NI.

如果AES-NI可用但您不想使用AES,则在启动程序之前执行以下操作:

$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)
    );
}

转载注明原文:如何检查OpenSSL是否支持/使用Intel AES-NI? - 代码日志