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 -----邮件原件----- 发件人: [email protected] [mailto:[email protected]] 代表 John 发送时间: 2013年12月6日 19:40 收件人: [email protected] 主题: Re: How can I enable aes-ni in openssl on Linux > On Thursday, December 5, 2013 6:55 PM, Matt Caswell <[email protected]> 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 [email protected] Automated List Manager [email protected]
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
