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.

Attachment: OpenSSLAESNIDemo.cpp
Description: Binary data

Reply via email to