如何检查OpenSSL是否支持/使用Intel AES-NI? [英] How can I check if OpenSSL is support/use the Intel AES-NI?

查看:660
本文介绍了如何检查OpenSSL是否支持/使用Intel AES-NI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

如何检查OpenSSL是否受支持/是否使用英特尔AES-NI?

它不是那么简单,尽管应该如此. OpenSSL用于提供获取ia32处理器检测到的功能的功能,但不再可用.请参见 OPENSSL_ia32cap手册页中对OPENSSL_ia32cap_loc的讨论. .另请参见在运行时验证AES-NI使用?在OpenSSL邮件列表中.

如果您要链接到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,因为它仅适用于库的静态链接.我在下面共享了用于检测的代码.我相信我从Intel的Dave Johnston(他设计了RDRAND电路)中删除了很大一部分.

注意 :以下代码可能会错误地拒绝具有AES-NI的AMD处理器.我没有要测试的处理器,所以我无法提供代码.

注意 :下面的代码将无法在Valgrind下正常运行. AES-NI或RDRAND指令没有仿真功能,因此Valgrind从CPUID返回医生"值,因此它们似乎不可用.请参阅邮件列表上的在Valgrind下运行时,内联汇编的错误结果. /p>


即使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)
    );
}

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

解决方案

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

这篇关于如何检查OpenSSL是否支持/使用Intel AES-NI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆