e_aes.c: integrate AESNI directly into EVP.
This commit is contained in:
		@@ -61,14 +61,213 @@
 | 
			
		||||
#include "modes_lcl.h"
 | 
			
		||||
#include <openssl/rand.h>
 | 
			
		||||
 | 
			
		||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 | 
			
		||||
					const unsigned char *iv, int enc);
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
	{
 | 
			
		||||
	AES_KEY ks;
 | 
			
		||||
	} EVP_AES_KEY;
 | 
			
		||||
 | 
			
		||||
#if	defined(AES_ASM) && !defined(I386_ONLY) &&	(  \
 | 
			
		||||
	((defined(__i386)	|| defined(__i386__)	|| \
 | 
			
		||||
	  defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
 | 
			
		||||
	defined(__x86_64)	|| defined(__x86_64__)	|| \
 | 
			
		||||
	defined(_M_AMD64)	|| defined(_M_X64)	|| \
 | 
			
		||||
	defined(__INTEL__)				)
 | 
			
		||||
 | 
			
		||||
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
 | 
			
		||||
			      AES_KEY *key);
 | 
			
		||||
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
 | 
			
		||||
			      AES_KEY *key);
 | 
			
		||||
 | 
			
		||||
void aesni_encrypt(const unsigned char *in, unsigned char *out,
 | 
			
		||||
		       const AES_KEY *key);
 | 
			
		||||
void aesni_decrypt(const unsigned char *in, unsigned char *out,
 | 
			
		||||
		       const AES_KEY *key);
 | 
			
		||||
 | 
			
		||||
void aesni_ecb_encrypt(const unsigned char *in,
 | 
			
		||||
			   unsigned char *out,
 | 
			
		||||
			   size_t length,
 | 
			
		||||
			   const AES_KEY *key,
 | 
			
		||||
			   int enc);
 | 
			
		||||
void aesni_cbc_encrypt(const unsigned char *in,
 | 
			
		||||
			   unsigned char *out,
 | 
			
		||||
			   size_t length,
 | 
			
		||||
			   const AES_KEY *key,
 | 
			
		||||
			   unsigned char *ivec, int enc);
 | 
			
		||||
 | 
			
		||||
void aesni_ctr32_encrypt_blocks(const unsigned char *in,
 | 
			
		||||
			   unsigned char *out,
 | 
			
		||||
			   size_t blocks,
 | 
			
		||||
			   const void *key,
 | 
			
		||||
			   const unsigned char *ivec);
 | 
			
		||||
 | 
			
		||||
extern unsigned int OPENSSL_ia32cap_P[2];
 | 
			
		||||
#define	AESNI_CAPABLE	(1<<(57-32))
 | 
			
		||||
 | 
			
		||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 | 
			
		||||
		   const unsigned char *iv, int enc)
 | 
			
		||||
	{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (((ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_ECB_MODE
 | 
			
		||||
	    || (ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_CBC_MODE)
 | 
			
		||||
	    && !enc) 
 | 
			
		||||
		ret = OPENSSL_ia32cap_P[1]&AESNI_CAPABLE ?
 | 
			
		||||
			aesni_set_decrypt_key(key, ctx->key_len*8, ctx->cipher_data):
 | 
			
		||||
			AES_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
 | 
			
		||||
	else
 | 
			
		||||
		ret = OPENSSL_ia32cap_P[1]&AESNI_CAPABLE ?
 | 
			
		||||
			aesni_set_encrypt_key(key, ctx->key_len*8, ctx->cipher_data):
 | 
			
		||||
			AES_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
 | 
			
		||||
 | 
			
		||||
	if(ret < 0)
 | 
			
		||||
		{
 | 
			
		||||
		EVPerr(EVP_F_AES_INIT_KEY,EVP_R_AES_KEY_SETUP_FAILED);
 | 
			
		||||
		return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 | 
			
		||||
	const unsigned char *in, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	if (OPENSSL_ia32cap_P[1]&AESNI_CAPABLE)
 | 
			
		||||
		aesni_cbc_encrypt(in,out,len,ctx->cipher_data,ctx->iv,ctx->encrypt);
 | 
			
		||||
	else
 | 
			
		||||
		AES_cbc_encrypt(in,out,len,ctx->cipher_data,ctx->iv,ctx->encrypt);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 | 
			
		||||
	const unsigned char *in, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	size_t	bl = ctx->cipher->block_size;
 | 
			
		||||
 | 
			
		||||
	if (len<bl)	return 1;
 | 
			
		||||
 | 
			
		||||
	if (OPENSSL_ia32cap_P[1]&AESNI_CAPABLE)
 | 
			
		||||
		aesni_ecb_encrypt(in,out,len,ctx->cipher_data,ctx->encrypt);
 | 
			
		||||
	else {
 | 
			
		||||
		size_t i;
 | 
			
		||||
 | 
			
		||||
		if (ctx->encrypt) {
 | 
			
		||||
			for (i=0,len-=bl;i<=len;i+=bl)
 | 
			
		||||
				AES_encrypt(in+i,out+i,ctx->cipher_data);
 | 
			
		||||
		} else {
 | 
			
		||||
			for (i=0,len-=bl;i<=len;i+=bl)
 | 
			
		||||
				AES_decrypt(in+i,out+i,ctx->cipher_data);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 | 
			
		||||
	const unsigned char *in,size_t len)
 | 
			
		||||
{
 | 
			
		||||
	CRYPTO_ofb128_encrypt(in,out,len,ctx->cipher_data,
 | 
			
		||||
			ctx->iv,&ctx->num,
 | 
			
		||||
			OPENSSL_ia32cap_P[1]&AESNI_CAPABLE ?
 | 
			
		||||
				(block128_f)aesni_encrypt  :
 | 
			
		||||
				(block128_f)AES_encrypt);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 | 
			
		||||
	const unsigned char *in,size_t len)
 | 
			
		||||
{
 | 
			
		||||
	CRYPTO_cfb128_encrypt(in,out,len,ctx->cipher_data,
 | 
			
		||||
			ctx->iv,&ctx->num,ctx->encrypt,
 | 
			
		||||
			OPENSSL_ia32cap_P[1]&AESNI_CAPABLE ?
 | 
			
		||||
				(block128_f)aesni_encrypt  :
 | 
			
		||||
				(block128_f)AES_encrypt);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 | 
			
		||||
	const unsigned char *in,size_t len)
 | 
			
		||||
{
 | 
			
		||||
	CRYPTO_cfb128_8_encrypt(in,out,len,ctx->cipher_data,
 | 
			
		||||
			ctx->iv,&ctx->num,ctx->encrypt,
 | 
			
		||||
			OPENSSL_ia32cap_P[1]&AESNI_CAPABLE ?
 | 
			
		||||
				(block128_f)aesni_encrypt  :
 | 
			
		||||
				(block128_f)AES_encrypt);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
 | 
			
		||||
	const unsigned char *in,size_t len)
 | 
			
		||||
{
 | 
			
		||||
	CRYPTO_cfb128_1_encrypt(in,out,len,ctx->cipher_data,
 | 
			
		||||
			ctx->iv,&ctx->num,ctx->encrypt,
 | 
			
		||||
			OPENSSL_ia32cap_P[1]&AESNI_CAPABLE ?
 | 
			
		||||
				(block128_f)aesni_encrypt  :
 | 
			
		||||
				(block128_f)AES_encrypt);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int aes_counter(EVP_CIPHER_CTX *ctx, unsigned char *out,
 | 
			
		||||
		const unsigned char *in, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int num;
 | 
			
		||||
	num = ctx->num;
 | 
			
		||||
 | 
			
		||||
	if (OPENSSL_ia32cap_P[1]&AESNI_CAPABLE)
 | 
			
		||||
		CRYPTO_ctr128_encrypt_ctr32(in,out,len,
 | 
			
		||||
			ctx->cipher_data,ctx->iv,ctx->buf,&num,
 | 
			
		||||
			(ctr128_f)aesni_ctr32_encrypt_blocks);
 | 
			
		||||
	else
 | 
			
		||||
		CRYPTO_ctr128_encrypt(in,out,len,
 | 
			
		||||
			ctx->cipher_data,ctx->iv,ctx->buf,&num,
 | 
			
		||||
			(block128_f)AES_encrypt);
 | 
			
		||||
	ctx->num = (size_t)num;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define BLOCK_CIPHER_mydef(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
 | 
			
		||||
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 &aes_##keylen##_##mode; }
 | 
			
		||||
 | 
			
		||||
#define BLOCK_CIPHER_mydefs(nid,keylen,flags)		\
 | 
			
		||||
	BLOCK_CIPHER_mydef(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 | 
			
		||||
	BLOCK_CIPHER_mydef(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 | 
			
		||||
	BLOCK_CIPHER_mydef(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 | 
			
		||||
	BLOCK_CIPHER_mydef(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)	\
 | 
			
		||||
	BLOCK_CIPHER_mydef(nid,keylen,1,16,cfb1,cfb1,CFB,flags)	\
 | 
			
		||||
	BLOCK_CIPHER_mydef(nid,keylen,1,16,cfb8,cfb8,CFB,flags)
 | 
			
		||||
 | 
			
		||||
BLOCK_CIPHER_mydefs(NID_aes,128,EVP_CIPH_FLAG_FIPS)
 | 
			
		||||
BLOCK_CIPHER_mydefs(NID_aes,192,EVP_CIPH_FLAG_FIPS)
 | 
			
		||||
BLOCK_CIPHER_mydefs(NID_aes,256,EVP_CIPH_FLAG_FIPS)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 | 
			
		||||
		   const unsigned char *iv, int enc)
 | 
			
		||||
	{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (((ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_ECB_MODE
 | 
			
		||||
	    || (ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_CBC_MODE)
 | 
			
		||||
	    && !enc) 
 | 
			
		||||
		ret=AES_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
 | 
			
		||||
	else
 | 
			
		||||
		ret=AES_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
 | 
			
		||||
 | 
			
		||||
	if(ret < 0)
 | 
			
		||||
		{
 | 
			
		||||
		EVPerr(EVP_F_AES_INIT_KEY,EVP_R_AES_KEY_SETUP_FAILED);
 | 
			
		||||
		return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define data(ctx)	EVP_C_DATA(EVP_AES_KEY,ctx)
 | 
			
		||||
 | 
			
		||||
IMPLEMENT_BLOCK_CIPHER(aes_128, ks, AES, EVP_AES_KEY,
 | 
			
		||||
@@ -116,6 +315,8 @@ static int aes_counter (EVP_CIPHER_CTX *ctx, unsigned char *out,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static const EVP_CIPHER aes_128_ctr_cipher=
 | 
			
		||||
	{
 | 
			
		||||
	NID_aes_128_ctr,1,16,16,
 | 
			
		||||
@@ -167,27 +368,6 @@ static const EVP_CIPHER aes_256_ctr_cipher=
 | 
			
		||||
const EVP_CIPHER *EVP_aes_256_ctr (void)
 | 
			
		||||
{	return &aes_256_ctr_cipher;	}
 | 
			
		||||
 | 
			
		||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 | 
			
		||||
		   const unsigned char *iv, int enc)
 | 
			
		||||
	{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (((ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_ECB_MODE
 | 
			
		||||
	    || (ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_CBC_MODE)
 | 
			
		||||
	    && !enc) 
 | 
			
		||||
		ret=AES_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
 | 
			
		||||
	else
 | 
			
		||||
		ret=AES_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
 | 
			
		||||
 | 
			
		||||
	if(ret < 0)
 | 
			
		||||
		{
 | 
			
		||||
		EVPerr(EVP_F_AES_INIT_KEY,EVP_R_AES_KEY_SETUP_FAILED);
 | 
			
		||||
		return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
	{
 | 
			
		||||
	/* AES key schedule to use */
 | 
			
		||||
@@ -482,7 +662,7 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 | 
			
		||||
	if (key)
 | 
			
		||||
		{
 | 
			
		||||
		/* key_len is two AES keys */
 | 
			
		||||
		if (ctx->encrypt)
 | 
			
		||||
		if (enc)
 | 
			
		||||
			{
 | 
			
		||||
			AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
 | 
			
		||||
			xctx->xts.block1 = (block128_f)AES_encrypt;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user