diff options
author | Andy Polyakov <appro@openssl.org> | 2011-06-28 14:49:35 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2011-06-28 14:49:35 +0000 |
commit | fbe2e28911070a8556ad05bdfd6b6871d4a82244 (patch) | |
tree | 630188a677ff340d121965f4d5593e0747d08752 /crypto/evp | |
parent | 84968e25f31c76b0e9043002b43bdcc6cad96fc2 (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.c | 387 |
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 |