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

 夏初如深秋123_929 发布于 2022-12-28 14:44

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

2 个回答
  • 根据jww提供的信息构建了几个快速的衬垫:

    openssl speed -elapsed -evp aes-128-cbc
    ...
    OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc
    ...
    

    第一行的输出应明显快于第二行.在我的情况下,在i5测试机器上,几乎翻倍.

    2022-12-28 14:46 回答
  • 如何检查OpenSSL是否支持/使用Intel AES-NI?

    它不是那么简单,尽管它应该是.OpenSSL曾经提供一种功能来获取ia32处理器检测到的功能,但它不再可用.见的讨论OPENSSL_ia32cap_locOPENSSL_ia32cap手册页.另请参阅验证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,因为它只适用于库的静态链接.我分享了下面用于检测的代码.我相信我从英特尔的戴夫约翰斯顿(他设计了RDRAND电路)中撕下了很大一部分.

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

    注意:下面的代码在Valgrind下不会按预期执行.对于AES-NI或RDRAND指令没有仿真,因此Valgrind返回"已修改"值,CPUID因此看起来它们不可用.在邮件列表上的 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)
        );
    }
    

    2022-12-28 14:48 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有