summaryrefslogtreecommitdiffstats
path: root/crypto/evp
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2011-06-28 14:49:35 +0000
committerAndy Polyakov <appro@openssl.org>2011-06-28 14:49:35 +0000
commitfbe2e28911070a8556ad05bdfd6b6871d4a82244 (patch)
tree630188a677ff340d121965f4d5593e0747d08752 /crypto/evp
parent84968e25f31c76b0e9043002b43bdcc6cad96fc2 (diff)
AES-NI backport from HEAD. Note that e_aes.c doesn't implement all modes
from HEAD yet, more will be back-ported later.
Diffstat (limited to 'crypto/evp')
-rw-r--r--crypto/evp/e_aes.c387
1 files changed, 288 insertions, 99 deletions
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 33679ca6b0..08468f755b 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -1,5 +1,5 @@
/* ====================================================================
- * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,117 +60,203 @@
#ifndef OPENSSL_FIPS
-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;
-#define data(ctx) EVP_C_DATA(EVP_AES_KEY,ctx)
-
-IMPLEMENT_BLOCK_CIPHER(aes_128, ks, AES, EVP_AES_KEY,
- NID_aes_128, 16, 16, 16, 128,
- 0, aes_init_key, NULL,
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL)
-IMPLEMENT_BLOCK_CIPHER(aes_192, ks, AES, EVP_AES_KEY,
- NID_aes_192, 16, 24, 16, 128,
- 0, aes_init_key, NULL,
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL)
-IMPLEMENT_BLOCK_CIPHER(aes_256, ks, AES, EVP_AES_KEY,
- NID_aes_256, 16, 32, 16, 128,
- 0, aes_init_key, NULL,
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL)
-
-#define IMPLEMENT_AES_CFBR(ksize,cbits) IMPLEMENT_CFBR(aes,AES,EVP_AES_KEY,ks,ksize,cbits,16)
-
-IMPLEMENT_AES_CFBR(128,1)
-IMPLEMENT_AES_CFBR(192,1)
-IMPLEMENT_AES_CFBR(256,1)
-
-IMPLEMENT_AES_CFBR(128,8)
-IMPLEMENT_AES_CFBR(192,8)
-IMPLEMENT_AES_CFBR(256,8)
-
-static int aes_counter (EVP_CIPHER_CTX *ctx, unsigned char *out,
+#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
+
+#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__) )
+/*
+ * AES-NI section
+ */
+extern unsigned int OPENSSL_ia32cap_P[2];
+#define AESNI_CAPABLE (1<<(57-32))
+
+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);
+
+static int aesni_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 = aesni_set_decrypt_key(key, ctx->key_len*8, ctx->cipher_data);
+ else
+ ret = aesni_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 aesni_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ aesni_cbc_encrypt(in,out,len,ctx->cipher_data,ctx->iv,ctx->encrypt);
+
+ return 1;
+}
+
+static int aesni_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;
+
+ aesni_ecb_encrypt(in,out,len,ctx->cipher_data,ctx->encrypt);
+
+ return 1;
+}
+
+static int aesni_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,
+ (block128_f)aesni_encrypt);
+ return 1;
+}
+
+static int aesni_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,
+ (block128_f)aesni_encrypt);
+ return 1;
+}
+
+static int aesni_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,
+ (block128_f)aesni_encrypt);
+ return 1;
+}
+
+static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
+ const unsigned char *in,size_t len)
+{
+ if (ctx->flags&EVP_CIPH_FLAG_LENGTH_BITS) {
+ CRYPTO_cfb128_1_encrypt(in,out,len,ctx->cipher_data,
+ ctx->iv,&ctx->num,ctx->encrypt,
+ (block128_f)aesni_encrypt);
+ return 1;
+ }
+
+ while (len>=MAXBITCHUNK) {
+ CRYPTO_cfb128_1_encrypt(in,out,MAXBITCHUNK*8,ctx->cipher_data,
+ ctx->iv,&ctx->num,ctx->encrypt,
+ (block128_f)aesni_encrypt);
+ len-=MAXBITCHUNK;
+ }
+ if (len)
+ CRYPTO_cfb128_1_encrypt(in,out,len*8,ctx->cipher_data,
+ ctx->iv,&ctx->num,ctx->encrypt,
+ (block128_f)aesni_encrypt);
+
+ return 1;
+}
+
+static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
unsigned int num;
num = ctx->num;
-#ifdef AES_CTR_ASM
- void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
- size_t blocks, const AES_KEY *key,
- const unsigned char ivec[AES_BLOCK_SIZE]);
CRYPTO_ctr128_encrypt_ctr32(in,out,len,
- &((EVP_AES_KEY *)ctx->cipher_data)->ks,
- ctx->iv,ctx->buf,&num,(ctr128_f)AES_ctr32_encrypt);
-#else
- CRYPTO_ctr128_encrypt(in,out,len,
- &((EVP_AES_KEY *)ctx->cipher_data)->ks,
- ctx->iv,ctx->buf,&num,(block128_f)AES_encrypt);
-#endif
+ ctx->cipher_data,ctx->iv,ctx->buf,&num,
+ (ctr128_f)aesni_ctr32_encrypt_blocks);
+
ctx->num = (size_t)num;
return 1;
}
-static const EVP_CIPHER aes_128_ctr_cipher=
- {
- NID_aes_128_ctr,1,16,16,
- EVP_CIPH_CTR_MODE,
- aes_init_key,
- aes_counter,
- NULL,
- sizeof(EVP_AES_KEY),
- NULL,
- NULL,
- NULL,
- NULL
- };
-
-const EVP_CIPHER *EVP_aes_128_ctr (void)
-{ return &aes_128_ctr_cipher; }
-
-static const EVP_CIPHER aes_192_ctr_cipher=
- {
- NID_aes_192_ctr,1,24,16,
- EVP_CIPH_CTR_MODE,
- aes_init_key,
- aes_counter,
- NULL,
- sizeof(EVP_AES_KEY),
- NULL,
- NULL,
- NULL,
- NULL
- };
-
-const EVP_CIPHER *EVP_aes_192_ctr (void)
-{ return &aes_192_ctr_cipher; }
-
-static const EVP_CIPHER aes_256_ctr_cipher=
- {
- NID_aes_256_ctr,1,32,16,
- EVP_CIPH_CTR_MODE,
- aes_init_key,
- aes_counter,
- NULL,
- sizeof(EVP_AES_KEY),
- NULL,
- NULL,
- NULL,
- NULL
- };
-
-const EVP_CIPHER *EVP_aes_256_ctr (void)
-{ return &aes_256_ctr_cipher; }
+#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 (OPENSSL_ia32cap_P[1]&AESNI_CAPABLE)? \
+ &aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
+
+#else
+
+#define BLOCK_CIPHER_generic(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; }
+#endif
+
+#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)
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
@@ -180,9 +266,9 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
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);
+ 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);
+ ret = AES_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
if(ret < 0)
{
@@ -193,6 +279,109 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
}
+static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ 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;
+ size_t i;
+
+ if (len<bl) return 1;
+
+ 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,
+ (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,
+ (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,
+ (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)
+{
+ if (ctx->flags&EVP_CIPH_FLAG_LENGTH_BITS) {
+ CRYPTO_cfb128_1_encrypt(in,out,len,ctx->cipher_data,
+ ctx->iv,&ctx->num,ctx->encrypt,
+ (block128_f)AES_encrypt);
+ return 1;
+ }
+
+ while (len>=MAXBITCHUNK) {
+ CRYPTO_cfb128_1_encrypt(in,out,MAXBITCHUNK*8,ctx->cipher_data,
+ ctx->iv,&ctx->num,ctx->encrypt,
+ (block128_f)AES_encrypt);
+ len-=MAXBITCHUNK;
+ }
+ if (len)
+ CRYPTO_cfb128_1_encrypt(in,out,len*8,ctx->cipher_data,
+ ctx->iv,&ctx->num,ctx->encrypt,
+ (block128_f)AES_encrypt);
+
+ return 1;
+}
+
+static int aes_ctr_cipher (EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ unsigned int num;
+ num = ctx->num;
+#ifdef AES_CTR_ASM
+ void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ const unsigned char ivec[AES_BLOCK_SIZE]);
+
+ CRYPTO_ctr128_encrypt_ctr32(in,out,len,
+ &((EVP_AES_KEY *)ctx->cipher_data)->ks,
+ ctx->iv,ctx->buf,&num,(ctr128_f)AES_ctr32_encrypt);
+#else
+ CRYPTO_ctr128_encrypt(in,out,len,
+ &((EVP_AES_KEY *)ctx->cipher_data)->ks,
+ ctx->iv,ctx->buf,&num,(block128_f)AES_encrypt);
#endif
+ ctx->num = (size_t)num;
+ return 1;
+}
+BLOCK_CIPHER_generic_pack(NID_aes,128,0)
+BLOCK_CIPHER_generic_pack(NID_aes,192,0)
+BLOCK_CIPHER_generic_pack(NID_aes,256,0)
+
+#endif
#endif