Hi John and all, I made one OpenSSL AES-NI study notes and one demo sample before, you can refer the enclosed files. By the way, you can also find some information from official Intel Developer Zone website for Intel AES-NI technology. http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-instructions-aes-ni/ Hope it is useful for you to enable AES-NI in OpenSSL.
B.R. Eason -----邮件原件----- 发件人: owner-openssl-us...@openssl.org [mailto:owner-openssl-us...@openssl.org] 代表 John 发送时间: 2013年12月6日 19:40 收件人: openssl-users@openssl.org 主题: Re: How can I enable aes-ni in openssl on Linux > On Thursday, December 5, 2013 6:55 PM, Matt Caswell <fr...@baggins.org> wrote: > The information in the linked pages is out of date for the latest > versions of openssl (>= 1.0.1). For these versions AES-NI does not > work via an engine and will not show up in the openssl engine command. > You are probably already running aes ni without realising it. > > See here for a discussion: > http://openssl.6102.n7.nabble.com/having-a-lot-of-troubles-trying-to-g > et-AES-NI-working-td44285.html Thanks for the link, Matt. And also thanks to Kane and Alan who kindly replied to my post. It does indeed seem that the info I linked is out-of-date and that aes-ni is enabled by default: Command A = openssl speed -elapsed -evp aes-128-cbc Command B = OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc Results: Command 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes ------------------------------------------------------------------------ A 796435.32k 845155.61k 852750.59k 860752.55k 865828.86k B 393740.06k 431465.71k 438168.23k 443452.42k 446458.54k ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org
1) Relevant Source .\crypto\aes\aes-586.pl .\crypto\aes\aesni-x86.pl .\crypto\aes\aes_core.c .\crypto\aes\aes.h .\crypto\aes\* .\crypto\evp\e_aes.c As AES_ASM is defined in makefile(.\ms\ntdll.mak) for compiling, AES relevant functions in aes-586.pl will be linked to replace the C implementation in aes_core.c. All AES-NI functions for IA32 platform are implemented in aesni-x86.pl In .\crypto\evp\e_aes.c, declared BLOCK_CIPHER_generic_pack(NID_aes,128,EVP_CIPH_FLAG_FIPS) BLOCK_CIPHER_generic_pack(NID_aes,192,EVP_CIPH_FLAG_FIPS) BLOCK_CIPHER_generic_pack(NID_aes,256,EVP_CIPH_FLAG_FIPS) ... #define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32))) ... #define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \ BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \ BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) \ BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags) ... #define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ static const EVP_CIPHER aesni_##keylen##_##mode = { \ nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ flags|EVP_CIPH_##MODE##_MODE, \ aesni_init_key, \ aesni_##mode##_cipher, \ NULL, \ sizeof(EVP_AES_KEY), \ NULL,NULL,NULL,NULL }; \ static const EVP_CIPHER aes_##keylen##_##mode = { \ nid##_##keylen##_##nmode,blocksize, \ keylen/8,ivlen, \ flags|EVP_CIPH_##MODE##_MODE, \ aes_init_key, \ aes_##mode##_cipher, \ NULL, \ sizeof(EVP_AES_KEY), \ NULL,NULL,NULL,NULL }; \ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ { return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; } ... So EVP_aes_##keylen##_##mode will check AESNI_CAPABLE(refer OPENSSL_ia32cap_P(.\cryptlib.c)) to determine whether to use general AES(with Intel IA32 accelerated) or use AES-NI. .\crypto\evp\evp_enc.c .\crypto\evp\evp.h int EVP_CipherInit( EVP_CIPHER_CTX *ctx , const EVP_CIPHER *cipher , const unsigned char *key , const unsigned char *iv , int enc); ctx: EVP_CIPHER context what will be initialized in EVP_CipherInit by calling EVP_CIPHER_CTX_init(set 0x00 as default) if the point of cipher method is not NULL cipher: EVP_CIPHER method for dedicated cipher function. For AES, OpenSSL provide EVP_CIPHER method as below: // list start const EVP_CIPHER *EVP_aes_128_ecb(void); const EVP_CIPHER *EVP_aes_128_cbc(void); const EVP_CIPHER *EVP_aes_128_cfb1(void); const EVP_CIPHER *EVP_aes_128_cfb8(void); const EVP_CIPHER *EVP_aes_128_cfb128(void); # define EVP_aes_128_cfb EVP_aes_128_cfb128 const EVP_CIPHER *EVP_aes_128_ofb(void); const EVP_CIPHER *EVP_aes_128_ctr(void); const EVP_CIPHER *EVP_aes_128_ccm(void); const EVP_CIPHER *EVP_aes_128_gcm(void); const EVP_CIPHER *EVP_aes_128_xts(void); const EVP_CIPHER *EVP_aes_192_ecb(void); const EVP_CIPHER *EVP_aes_192_cbc(void); const EVP_CIPHER *EVP_aes_192_cfb1(void); const EVP_CIPHER *EVP_aes_192_cfb8(void); const EVP_CIPHER *EVP_aes_192_cfb128(void); # define EVP_aes_192_cfb EVP_aes_192_cfb128 const EVP_CIPHER *EVP_aes_192_ofb(void); const EVP_CIPHER *EVP_aes_192_ctr(void); const EVP_CIPHER *EVP_aes_192_ccm(void); const EVP_CIPHER *EVP_aes_192_gcm(void); const EVP_CIPHER *EVP_aes_256_ecb(void); const EVP_CIPHER *EVP_aes_256_cbc(void); const EVP_CIPHER *EVP_aes_256_cfb1(void); const EVP_CIPHER *EVP_aes_256_cfb8(void); const EVP_CIPHER *EVP_aes_256_cfb128(void); # define EVP_aes_256_cfb EVP_aes_256_cfb128 const EVP_CIPHER *EVP_aes_256_ofb(void); const EVP_CIPHER *EVP_aes_256_ctr(void); const EVP_CIPHER *EVP_aes_256_ccm(void); const EVP_CIPHER *EVP_aes_256_gcm(void); const EVP_CIPHER *EVP_aes_256_xts(void); // list end key: AES key iv: AES initialization vector enc: work mode; 1: encrypt, 0: decrypt return: 1: success; 0: failed with EVPerr int EVP_CipherUpdate( EVP_CIPHER_CTX *ctx , unsigned char *out , int *outl , const unsigned char *in , int inl); ctx: EVP_CIPHER context out: point of output buffer outl: point of output buffer in: point of input buffer inl: input buffer length, should be multiple of block size return: 1: success; 0: failed with EVPerr int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); ctx: EVP_CIPHER context outm: point of output buffer outl: point of output buffer length This function may handle last input buffer block with ((inputBufferLength % blockSize) + (padding data)) 2) Usage Please refer OpenSSLAESNIDemo package.
OpenSSLAESNIDemo.cpp
Description: Binary data