components/openssl/openssl-1.0.0/engines/aesni/eng_aesni.c
branchs11-update
changeset 2593 b92e6df5eaf0
parent 2592 a7d8d41eeab2
child 2594 27f414f634e9
equal deleted inserted replaced
2592:a7d8d41eeab2 2593:b92e6df5eaf0
     1 /*
       
     2  * Support for Intel AES-NI intruction set
       
     3  *   Author: Huang Ying <[email protected]>
       
     4  *
       
     5  * Intel AES-NI is a new set of Single Instruction Multiple Data
       
     6  * (SIMD) instructions that are going to be introduced in the next
       
     7  * generation of Intel processor, as of 2009. These instructions
       
     8  * enable fast and secure data encryption and decryption, using the
       
     9  * Advanced Encryption Standard (AES), defined by FIPS Publication
       
    10  * number 197.  The architecture introduces six instructions that
       
    11  * offer full hardware support for AES. Four of them support high
       
    12  * performance data encryption and decryption, and the other two
       
    13  * instructions support the AES key expansion procedure.
       
    14  *
       
    15  * The white paper can be downloaded from:
       
    16  *   http://softwarecommunity.intel.com/isn/downloads/intelavx/AES-Instructions-Set_WP.pdf
       
    17  *
       
    18  * This file is based on engines/e_padlock.c
       
    19  */
       
    20 
       
    21 /* ====================================================================
       
    22  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
       
    23  *
       
    24  * Redistribution and use in source and binary forms, with or without
       
    25  * modification, are permitted provided that the following conditions
       
    26  * are met:
       
    27  *
       
    28  * 1. Redistributions of source code must retain the above copyright
       
    29  *    notice, this list of conditions and the following disclaimer.
       
    30  *
       
    31  * 2. Redistributions in binary form must reproduce the above copyright
       
    32  *    notice, this list of conditions and the following disclaimer in
       
    33  *    the documentation and/or other materials provided with the
       
    34  *    distribution.
       
    35  *
       
    36  * 3. All advertising materials mentioning features or use of this
       
    37  *    software must display the following acknowledgment:
       
    38  *    "This product includes software developed by the OpenSSL Project
       
    39  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
       
    40  *
       
    41  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
       
    42  *    endorse or promote products derived from this software without
       
    43  *    prior written permission. For written permission, please contact
       
    44  *    [email protected].
       
    45  *
       
    46  * 5. Products derived from this software may not be called "OpenSSL"
       
    47  *    nor may "OpenSSL" appear in their names without prior written
       
    48  *    permission of the OpenSSL Project.
       
    49  *
       
    50  * 6. Redistributions of any form whatsoever must retain the following
       
    51  *    acknowledgment:
       
    52  *    "This product includes software developed by the OpenSSL Project
       
    53  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
       
    54  *
       
    55  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
       
    56  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    58  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
       
    59  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    60  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
       
    61  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    62  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
       
    64  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    65  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
       
    66  * OF THE POSSIBILITY OF SUCH DAMAGE.
       
    67  * ====================================================================
       
    68  *
       
    69  * This product includes cryptographic software written by Eric Young
       
    70  * ([email protected]).  This product includes software written by Tim
       
    71  * Hudson ([email protected]).
       
    72  *
       
    73  */
       
    74 
       
    75 
       
    76 #include <openssl/opensslconf.h>
       
    77 
       
    78 #if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_AES_NI) && !defined(OPENSSL_NO_AES)
       
    79 
       
    80 #include <stdio.h>
       
    81 #include "cryptlib.h"
       
    82 #include <openssl/dso.h>
       
    83 #include <openssl/engine.h>
       
    84 #include <openssl/evp.h>
       
    85 #include <openssl/aes.h>
       
    86 #include <openssl/err.h>
       
    87 #include <openssl/modes.h>
       
    88 
       
    89 /* AES-NI is available *ONLY* on some x86 CPUs.  Not only that it
       
    90    doesn't exist elsewhere, but it even can't be compiled on other
       
    91    platforms! */
       
    92 #undef COMPILE_HW_AESNI
       
    93 #if (defined(__x86_64) || defined(__x86_64__) || \
       
    94      defined(_M_AMD64) || defined(_M_X64) || \
       
    95      defined(OPENSSL_IA32_SSE2)) && !defined(OPENSSL_NO_ASM)
       
    96 #define COMPILE_HW_AESNI
       
    97 static ENGINE *ENGINE_aesni (void);
       
    98 #endif
       
    99 
       
   100 void ENGINE_load_aesni (void)
       
   101 {
       
   102 /* On non-x86 CPUs it just returns. */
       
   103 #ifdef COMPILE_HW_AESNI
       
   104 	ENGINE *toadd = ENGINE_aesni();
       
   105 	if (!toadd)
       
   106 		return;
       
   107 	ENGINE_add (toadd);
       
   108 	ENGINE_free (toadd);
       
   109 	ERR_clear_error ();
       
   110 #endif
       
   111 }
       
   112 
       
   113 #ifdef COMPILE_HW_AESNI
       
   114 int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
       
   115 			      AES_KEY *key);
       
   116 int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
       
   117 			      AES_KEY *key);
       
   118 
       
   119 void aesni_encrypt(const unsigned char *in, unsigned char *out,
       
   120 		       const AES_KEY *key);
       
   121 void aesni_decrypt(const unsigned char *in, unsigned char *out,
       
   122 		       const AES_KEY *key);
       
   123 
       
   124 void aesni_ecb_encrypt(const unsigned char *in,
       
   125 			   unsigned char *out,
       
   126 			   size_t length,
       
   127 			   const AES_KEY *key,
       
   128 			   int enc);
       
   129 void aesni_cbc_encrypt(const unsigned char *in,
       
   130 			   unsigned char *out,
       
   131 			   size_t length,
       
   132 			   const AES_KEY *key,
       
   133 			   unsigned char *ivec, int enc);
       
   134 
       
   135 /* Function for ENGINE detection and control */
       
   136 static int aesni_init(ENGINE *e);
       
   137 
       
   138 /* Cipher Stuff */
       
   139 static int aesni_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
       
   140 				const int **nids, int nid);
       
   141 
       
   142 #define AESNI_MIN_ALIGN	16
       
   143 #define AESNI_ALIGN(x) \
       
   144 	((void *)(((unsigned long)(x)+AESNI_MIN_ALIGN-1)&~(AESNI_MIN_ALIGN-1)))
       
   145 
       
   146 /* Engine names */
       
   147 static const char   aesni_id[] = "aesni",
       
   148 		    aesni_name[] = "Intel AES-NI engine",
       
   149 		    no_aesni_name[] = "Intel AES-NI engine (no-aesni)";
       
   150 
       
   151 /* ===== Engine "management" functions ===== */
       
   152 
       
   153 #if defined(_WIN32)
       
   154 typedef unsigned __int64 IA32CAP;
       
   155 #else
       
   156 typedef unsigned long long IA32CAP;
       
   157 #endif
       
   158 
       
   159 /* Prepare the ENGINE structure for registration */
       
   160 static int
       
   161 aesni_bind_helper(ENGINE *e)
       
   162 {
       
   163 	int engage;
       
   164 	if (sizeof(OPENSSL_ia32cap_P) > 4) {
       
   165 		engage = (int)((OPENSSL_ia32cap_P >> 30) >> 27) & 1;
       
   166 	} else {
       
   167 		IA32CAP OPENSSL_ia32_cpuid(void);
       
   168 		engage = (int)(OPENSSL_ia32_cpuid() >> 57) & 1;
       
   169 	}
       
   170 
       
   171 	/* Register everything or return with an error */
       
   172 	if (!ENGINE_set_id(e, aesni_id) ||
       
   173 	    !ENGINE_set_name(e, engage ? aesni_name : no_aesni_name) ||
       
   174 
       
   175 	    !ENGINE_set_init_function(e, aesni_init) ||
       
   176 	    (engage && !ENGINE_set_ciphers (e, aesni_ciphers))
       
   177 	    )
       
   178 		return 0;
       
   179 
       
   180 	/* Everything looks good */
       
   181 	return 1;
       
   182 }
       
   183 
       
   184 /* Constructor */
       
   185 static ENGINE *
       
   186 ENGINE_aesni(void)
       
   187 {
       
   188 	ENGINE *eng = ENGINE_new();
       
   189 
       
   190 	if (!eng) {
       
   191 		return NULL;
       
   192 	}
       
   193 
       
   194 	if (!aesni_bind_helper(eng)) {
       
   195 		ENGINE_free(eng);
       
   196 		return NULL;
       
   197 	}
       
   198 
       
   199 	return eng;
       
   200 }
       
   201 
       
   202 /* Check availability of the engine */
       
   203 static int
       
   204 aesni_init(ENGINE *e)
       
   205 {
       
   206 	return 1;
       
   207 }
       
   208 
       
   209 #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
       
   210 #define NID_aes_128_cfb	NID_aes_128_cfb128
       
   211 #endif
       
   212 
       
   213 #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
       
   214 #define NID_aes_128_ofb	NID_aes_128_ofb128
       
   215 #endif
       
   216 
       
   217 #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
       
   218 #define NID_aes_192_cfb	NID_aes_192_cfb128
       
   219 #endif
       
   220 
       
   221 #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
       
   222 #define NID_aes_192_ofb	NID_aes_192_ofb128
       
   223 #endif
       
   224 
       
   225 #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
       
   226 #define NID_aes_256_cfb	NID_aes_256_cfb128
       
   227 #endif
       
   228 
       
   229 #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
       
   230 #define NID_aes_256_ofb	NID_aes_256_ofb128
       
   231 #endif
       
   232 
       
   233 /* List of supported ciphers. */
       
   234 static int aesni_cipher_nids[] = {
       
   235 	NID_aes_128_ecb,
       
   236 	NID_aes_128_cbc,
       
   237 	NID_aes_128_cfb,
       
   238 	NID_aes_128_ofb,
       
   239 
       
   240 	NID_aes_192_ecb,
       
   241 	NID_aes_192_cbc,
       
   242 	NID_aes_192_cfb,
       
   243 	NID_aes_192_ofb,
       
   244 
       
   245 	NID_aes_256_ecb,
       
   246 	NID_aes_256_cbc,
       
   247 	NID_aes_256_cfb,
       
   248 	NID_aes_256_ofb,
       
   249 };
       
   250 static int aesni_cipher_nids_num =
       
   251 	(sizeof(aesni_cipher_nids)/sizeof(aesni_cipher_nids[0]));
       
   252 
       
   253 typedef struct
       
   254 {
       
   255 	AES_KEY ks;
       
   256 	unsigned int _pad1[3];
       
   257 } AESNI_KEY;
       
   258 
       
   259 static int
       
   260 aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *user_key,
       
   261 		    const unsigned char *iv, int enc)
       
   262 {
       
   263 	int ret;
       
   264 	AES_KEY *key = AESNI_ALIGN(ctx->cipher_data);
       
   265 
       
   266 	if ((ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_CFB_MODE
       
   267 	    || (ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_OFB_MODE
       
   268 	    || enc)
       
   269 		ret=aesni_set_encrypt_key(user_key, ctx->key_len * 8, key);
       
   270 	else
       
   271 		ret=aesni_set_decrypt_key(user_key, ctx->key_len * 8, key);
       
   272 
       
   273 	if(ret < 0) {
       
   274 		EVPerr(EVP_F_AESNI_INIT_KEY,EVP_R_AES_KEY_SETUP_FAILED);
       
   275 		return 0;
       
   276 	}
       
   277 
       
   278 	return 1;
       
   279 }
       
   280 
       
   281 static int aesni_cipher_ecb(EVP_CIPHER_CTX *ctx, unsigned char *out,
       
   282 		 const unsigned char *in, size_t inl)
       
   283 {	AES_KEY *key = AESNI_ALIGN(ctx->cipher_data);
       
   284 	aesni_ecb_encrypt(in, out, inl, key, ctx->encrypt);
       
   285 	return 1;
       
   286 }
       
   287 static int aesni_cipher_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
       
   288 		 const unsigned char *in, size_t inl)
       
   289 {	AES_KEY *key = AESNI_ALIGN(ctx->cipher_data);
       
   290 	aesni_cbc_encrypt(in, out, inl, key,
       
   291 			      ctx->iv, ctx->encrypt);
       
   292 	return 1;
       
   293 }
       
   294 static int aesni_cipher_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
       
   295 		 const unsigned char *in, size_t inl)
       
   296 {	AES_KEY *key = AESNI_ALIGN(ctx->cipher_data);
       
   297 	CRYPTO_cfb128_encrypt(in, out, inl, key, ctx->iv,
       
   298 				&ctx->num, ctx->encrypt,
       
   299 				(block128_f)aesni_encrypt);
       
   300 	return 1;
       
   301 }
       
   302 static int aesni_cipher_ofb(EVP_CIPHER_CTX *ctx, unsigned char *out,
       
   303 		 const unsigned char *in, size_t inl)
       
   304 {	AES_KEY *key = AESNI_ALIGN(ctx->cipher_data);
       
   305 	CRYPTO_ofb128_encrypt(in, out, inl, key, ctx->iv,
       
   306 				&ctx->num, (block128_f)aesni_encrypt);
       
   307 	return 1;
       
   308 }
       
   309 
       
   310 #define AES_BLOCK_SIZE		16
       
   311 
       
   312 #define EVP_CIPHER_block_size_ECB	AES_BLOCK_SIZE
       
   313 #define EVP_CIPHER_block_size_CBC	AES_BLOCK_SIZE
       
   314 #define EVP_CIPHER_block_size_OFB	1
       
   315 #define EVP_CIPHER_block_size_CFB	1
       
   316 
       
   317 /* Declaring so many ciphers by hand would be a pain.
       
   318    Instead introduce a bit of preprocessor magic :-) */
       
   319 #define	DECLARE_AES_EVP(ksize,lmode,umode)	\
       
   320 static const EVP_CIPHER aesni_##ksize##_##lmode = {	\
       
   321 	NID_aes_##ksize##_##lmode,			\
       
   322 	EVP_CIPHER_block_size_##umode,			\
       
   323 	ksize / 8,					\
       
   324 	AES_BLOCK_SIZE,					\
       
   325 	0 | EVP_CIPH_##umode##_MODE,			\
       
   326 	aesni_init_key,				\
       
   327 	aesni_cipher_##lmode,				\
       
   328 	NULL,						\
       
   329 	sizeof(AESNI_KEY),				\
       
   330 	EVP_CIPHER_set_asn1_iv,				\
       
   331 	EVP_CIPHER_get_asn1_iv,				\
       
   332 	NULL,						\
       
   333 	NULL						\
       
   334 }
       
   335 
       
   336 DECLARE_AES_EVP(128,ecb,ECB);
       
   337 DECLARE_AES_EVP(128,cbc,CBC);
       
   338 DECLARE_AES_EVP(128,cfb,CFB);
       
   339 DECLARE_AES_EVP(128,ofb,OFB);
       
   340 
       
   341 DECLARE_AES_EVP(192,ecb,ECB);
       
   342 DECLARE_AES_EVP(192,cbc,CBC);
       
   343 DECLARE_AES_EVP(192,cfb,CFB);
       
   344 DECLARE_AES_EVP(192,ofb,OFB);
       
   345 
       
   346 DECLARE_AES_EVP(256,ecb,ECB);
       
   347 DECLARE_AES_EVP(256,cbc,CBC);
       
   348 DECLARE_AES_EVP(256,cfb,CFB);
       
   349 DECLARE_AES_EVP(256,ofb,OFB);
       
   350 
       
   351 static int
       
   352 aesni_ciphers (ENGINE *e, const EVP_CIPHER **cipher,
       
   353 		      const int **nids, int nid)
       
   354 {
       
   355 	/* No specific cipher => return a list of supported nids ... */
       
   356 	if (!cipher) {
       
   357 		*nids = aesni_cipher_nids;
       
   358 		return aesni_cipher_nids_num;
       
   359 	}
       
   360 
       
   361 	/* ... or the requested "cipher" otherwise */
       
   362 	switch (nid) {
       
   363 	case NID_aes_128_ecb:
       
   364 		*cipher = &aesni_128_ecb;
       
   365 		break;
       
   366 	case NID_aes_128_cbc:
       
   367 		*cipher = &aesni_128_cbc;
       
   368 		break;
       
   369 	case NID_aes_128_cfb:
       
   370 		*cipher = &aesni_128_cfb;
       
   371 		break;
       
   372 	case NID_aes_128_ofb:
       
   373 		*cipher = &aesni_128_ofb;
       
   374 		break;
       
   375 
       
   376 	case NID_aes_192_ecb:
       
   377 		*cipher = &aesni_192_ecb;
       
   378 		break;
       
   379 	case NID_aes_192_cbc:
       
   380 		*cipher = &aesni_192_cbc;
       
   381 		break;
       
   382 	case NID_aes_192_cfb:
       
   383 		*cipher = &aesni_192_cfb;
       
   384 		break;
       
   385 	case NID_aes_192_ofb:
       
   386 		*cipher = &aesni_192_ofb;
       
   387 		break;
       
   388 
       
   389 	case NID_aes_256_ecb:
       
   390 		*cipher = &aesni_256_ecb;
       
   391 		break;
       
   392 	case NID_aes_256_cbc:
       
   393 		*cipher = &aesni_256_cbc;
       
   394 		break;
       
   395 	case NID_aes_256_cfb:
       
   396 		*cipher = &aesni_256_cfb;
       
   397 		break;
       
   398 	case NID_aes_256_ofb:
       
   399 		*cipher = &aesni_256_ofb;
       
   400 		break;
       
   401 
       
   402 	default:
       
   403 		/* Sorry, we don't support this NID */
       
   404 		*cipher = NULL;
       
   405 		return 0;
       
   406 	}
       
   407 
       
   408 	return 1;
       
   409 }
       
   410 
       
   411 #endif /* COMPILE_HW_AESNI */
       
   412 #endif /* !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_AESNI) && !defined(OPENSSL_NO_AES) */