aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/crypto/aesni-intel_glue.c
diff options
context:
space:
mode:
authorTimothy McCaffrey <timothy.mccaffrey@unisys.com>2015-01-13 13:16:43 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2015-01-14 05:56:51 -0500
commite31ac32d3bc27c33f002e0c9ffd6ae08b65474e6 (patch)
treee2f11e810e52f8aa8a1b5e813a64ef56f1c1a6a6 /arch/x86/crypto/aesni-intel_glue.c
parentd8219f52a72033f84c15cde73294d46578fb2d68 (diff)
crypto: aesni - Add support for 192 & 256 bit keys to AESNI RFC4106
These patches fix the RFC4106 implementation in the aesni-intel module so it supports 192 & 256 bit keys. Since the AVX support that was added to this module also only supports 128 bit keys, and this patch only affects the SSE implementation, changes were also made to use the SSE version if key sizes other than 128 are specified. RFC4106 specifies that 192 & 256 bit keys must be supported (section 8.4). Also, this should fix Strongswan issue 341 where the aesni module needs to be unloaded if 256 bit keys are used: http://wiki.strongswan.org/issues/341 This patch has been tested with Sandy Bridge and Haswell processors. With 128 bit keys and input buffers > 512 bytes a slight performance degradation was noticed (~1%). For input buffers of less than 512 bytes there was no performance impact. Compared to 128 bit keys, 256 bit key size performance is approx. .5 cycles per byte slower on Sandy Bridge, and .37 cycles per byte slower on Haswell (vs. SSE code). This patch has also been tested with StrongSwan IPSec connections where it worked correctly. I created this diff from a git clone of crypto-2.6.git. Any questions, please feel free to contact me. Signed-off-by: Timothy McCaffrey <timothy.mccaffrey@unisys.com> Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'arch/x86/crypto/aesni-intel_glue.c')
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index ae855f4f64b7..947c6bf52c33 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -43,6 +43,7 @@
43#include <asm/crypto/glue_helper.h> 43#include <asm/crypto/glue_helper.h>
44#endif 44#endif
45 45
46
46/* This data is stored at the end of the crypto_tfm struct. 47/* This data is stored at the end of the crypto_tfm struct.
47 * It's a type of per "session" data storage location. 48 * It's a type of per "session" data storage location.
48 * This needs to be 16 byte aligned. 49 * This needs to be 16 byte aligned.
@@ -182,7 +183,8 @@ static void aesni_gcm_enc_avx(void *ctx, u8 *out,
182 u8 *hash_subkey, const u8 *aad, unsigned long aad_len, 183 u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
183 u8 *auth_tag, unsigned long auth_tag_len) 184 u8 *auth_tag, unsigned long auth_tag_len)
184{ 185{
185 if (plaintext_len < AVX_GEN2_OPTSIZE) { 186 struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
187 if ((plaintext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)){
186 aesni_gcm_enc(ctx, out, in, plaintext_len, iv, hash_subkey, aad, 188 aesni_gcm_enc(ctx, out, in, plaintext_len, iv, hash_subkey, aad,
187 aad_len, auth_tag, auth_tag_len); 189 aad_len, auth_tag, auth_tag_len);
188 } else { 190 } else {
@@ -197,7 +199,8 @@ static void aesni_gcm_dec_avx(void *ctx, u8 *out,
197 u8 *hash_subkey, const u8 *aad, unsigned long aad_len, 199 u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
198 u8 *auth_tag, unsigned long auth_tag_len) 200 u8 *auth_tag, unsigned long auth_tag_len)
199{ 201{
200 if (ciphertext_len < AVX_GEN2_OPTSIZE) { 202 struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
203 if ((ciphertext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)) {
201 aesni_gcm_dec(ctx, out, in, ciphertext_len, iv, hash_subkey, aad, 204 aesni_gcm_dec(ctx, out, in, ciphertext_len, iv, hash_subkey, aad,
202 aad_len, auth_tag, auth_tag_len); 205 aad_len, auth_tag, auth_tag_len);
203 } else { 206 } else {
@@ -231,7 +234,8 @@ static void aesni_gcm_enc_avx2(void *ctx, u8 *out,
231 u8 *hash_subkey, const u8 *aad, unsigned long aad_len, 234 u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
232 u8 *auth_tag, unsigned long auth_tag_len) 235 u8 *auth_tag, unsigned long auth_tag_len)
233{ 236{
234 if (plaintext_len < AVX_GEN2_OPTSIZE) { 237 struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
238 if ((plaintext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)) {
235 aesni_gcm_enc(ctx, out, in, plaintext_len, iv, hash_subkey, aad, 239 aesni_gcm_enc(ctx, out, in, plaintext_len, iv, hash_subkey, aad,
236 aad_len, auth_tag, auth_tag_len); 240 aad_len, auth_tag, auth_tag_len);
237 } else if (plaintext_len < AVX_GEN4_OPTSIZE) { 241 } else if (plaintext_len < AVX_GEN4_OPTSIZE) {
@@ -250,7 +254,8 @@ static void aesni_gcm_dec_avx2(void *ctx, u8 *out,
250 u8 *hash_subkey, const u8 *aad, unsigned long aad_len, 254 u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
251 u8 *auth_tag, unsigned long auth_tag_len) 255 u8 *auth_tag, unsigned long auth_tag_len)
252{ 256{
253 if (ciphertext_len < AVX_GEN2_OPTSIZE) { 257 struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
258 if ((ciphertext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)) {
254 aesni_gcm_dec(ctx, out, in, ciphertext_len, iv, hash_subkey, 259 aesni_gcm_dec(ctx, out, in, ciphertext_len, iv, hash_subkey,
255 aad, aad_len, auth_tag, auth_tag_len); 260 aad, aad_len, auth_tag, auth_tag_len);
256 } else if (ciphertext_len < AVX_GEN4_OPTSIZE) { 261 } else if (ciphertext_len < AVX_GEN4_OPTSIZE) {
@@ -511,7 +516,7 @@ static int ctr_crypt(struct blkcipher_desc *desc,
511 kernel_fpu_begin(); 516 kernel_fpu_begin();
512 while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) { 517 while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
513 aesni_ctr_enc_tfm(ctx, walk.dst.virt.addr, walk.src.virt.addr, 518 aesni_ctr_enc_tfm(ctx, walk.dst.virt.addr, walk.src.virt.addr,
514 nbytes & AES_BLOCK_MASK, walk.iv); 519 nbytes & AES_BLOCK_MASK, walk.iv);
515 nbytes &= AES_BLOCK_SIZE - 1; 520 nbytes &= AES_BLOCK_SIZE - 1;
516 err = blkcipher_walk_done(desc, &walk, nbytes); 521 err = blkcipher_walk_done(desc, &walk, nbytes);
517 } 522 }
@@ -902,7 +907,8 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
902 } 907 }
903 /*Account for 4 byte nonce at the end.*/ 908 /*Account for 4 byte nonce at the end.*/
904 key_len -= 4; 909 key_len -= 4;
905 if (key_len != AES_KEYSIZE_128) { 910 if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 &&
911 key_len != AES_KEYSIZE_256) {
906 crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 912 crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
907 return -EINVAL; 913 return -EINVAL;
908 } 914 }
@@ -1013,6 +1019,7 @@ static int __driver_rfc4106_encrypt(struct aead_request *req)
1013 __be32 counter = cpu_to_be32(1); 1019 __be32 counter = cpu_to_be32(1);
1014 struct crypto_aead *tfm = crypto_aead_reqtfm(req); 1020 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1015 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); 1021 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
1022 u32 key_len = ctx->aes_key_expanded.key_length;
1016 void *aes_ctx = &(ctx->aes_key_expanded); 1023 void *aes_ctx = &(ctx->aes_key_expanded);
1017 unsigned long auth_tag_len = crypto_aead_authsize(tfm); 1024 unsigned long auth_tag_len = crypto_aead_authsize(tfm);
1018 u8 iv_tab[16+AESNI_ALIGN]; 1025 u8 iv_tab[16+AESNI_ALIGN];
@@ -1027,6 +1034,13 @@ static int __driver_rfc4106_encrypt(struct aead_request *req)
1027 /* to 8 or 12 bytes */ 1034 /* to 8 or 12 bytes */
1028 if (unlikely(req->assoclen != 8 && req->assoclen != 12)) 1035 if (unlikely(req->assoclen != 8 && req->assoclen != 12))
1029 return -EINVAL; 1036 return -EINVAL;
1037 if (unlikely(auth_tag_len != 8 && auth_tag_len != 12 && auth_tag_len != 16))
1038 return -EINVAL;
1039 if (unlikely(key_len != AES_KEYSIZE_128 &&
1040 key_len != AES_KEYSIZE_192 &&
1041 key_len != AES_KEYSIZE_256))
1042 return -EINVAL;
1043
1030 /* IV below built */ 1044 /* IV below built */
1031 for (i = 0; i < 4; i++) 1045 for (i = 0; i < 4; i++)
1032 *(iv+i) = ctx->nonce[i]; 1046 *(iv+i) = ctx->nonce[i];
@@ -1091,6 +1105,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
1091 int retval = 0; 1105 int retval = 0;
1092 struct crypto_aead *tfm = crypto_aead_reqtfm(req); 1106 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1093 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); 1107 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
1108 u32 key_len = ctx->aes_key_expanded.key_length;
1094 void *aes_ctx = &(ctx->aes_key_expanded); 1109 void *aes_ctx = &(ctx->aes_key_expanded);
1095 unsigned long auth_tag_len = crypto_aead_authsize(tfm); 1110 unsigned long auth_tag_len = crypto_aead_authsize(tfm);
1096 u8 iv_and_authTag[32+AESNI_ALIGN]; 1111 u8 iv_and_authTag[32+AESNI_ALIGN];
@@ -1104,6 +1119,13 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
1104 if (unlikely((req->cryptlen < auth_tag_len) || 1119 if (unlikely((req->cryptlen < auth_tag_len) ||
1105 (req->assoclen != 8 && req->assoclen != 12))) 1120 (req->assoclen != 8 && req->assoclen != 12)))
1106 return -EINVAL; 1121 return -EINVAL;
1122 if (unlikely(auth_tag_len != 8 && auth_tag_len != 12 && auth_tag_len != 16))
1123 return -EINVAL;
1124 if (unlikely(key_len != AES_KEYSIZE_128 &&
1125 key_len != AES_KEYSIZE_192 &&
1126 key_len != AES_KEYSIZE_256))
1127 return -EINVAL;
1128
1107 /* Assuming we are supporting rfc4106 64-bit extended */ 1129 /* Assuming we are supporting rfc4106 64-bit extended */
1108 /* sequence numbers We need to have the AAD length */ 1130 /* sequence numbers We need to have the AAD length */
1109 /* equal to 8 or 12 bytes */ 1131 /* equal to 8 or 12 bytes */