diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2014-03-27 13:14:40 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2014-04-01 05:22:47 -0400 |
commit | 8ceee72808d1ae3fb191284afc2257a2be964725 (patch) | |
tree | 30112eda2dac48ea04c9bd035dd918b82a47c2af /arch | |
parent | 37b28947170ebe55cb4f689ded5857d943c6578e (diff) |
crypto: ghash-clmulni-intel - use C implementation for setkey()
The GHASH setkey() function uses SSE registers but fails to call
kernel_fpu_begin()/kernel_fpu_end(). Instead of adding these calls, and
then having to deal with the restriction that they cannot be called from
interrupt context, move the setkey() implementation to the C domain.
Note that setkey() does not use any particular SSE features and is not
expected to become a performance bottleneck.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
Fixes: 0e1227d356e9b (crypto: ghash - Add PCLMULQDQ accelerated implementation)
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/crypto/ghash-clmulni-intel_asm.S | 29 | ||||
-rw-r--r-- | arch/x86/crypto/ghash-clmulni-intel_glue.c | 14 |
2 files changed, 11 insertions, 32 deletions
diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S index 586f41aac361..185fad49d86f 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_asm.S +++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S | |||
@@ -24,10 +24,6 @@ | |||
24 | .align 16 | 24 | .align 16 |
25 | .Lbswap_mask: | 25 | .Lbswap_mask: |
26 | .octa 0x000102030405060708090a0b0c0d0e0f | 26 | .octa 0x000102030405060708090a0b0c0d0e0f |
27 | .Lpoly: | ||
28 | .octa 0xc2000000000000000000000000000001 | ||
29 | .Ltwo_one: | ||
30 | .octa 0x00000001000000000000000000000001 | ||
31 | 27 | ||
32 | #define DATA %xmm0 | 28 | #define DATA %xmm0 |
33 | #define SHASH %xmm1 | 29 | #define SHASH %xmm1 |
@@ -134,28 +130,3 @@ ENTRY(clmul_ghash_update) | |||
134 | .Lupdate_just_ret: | 130 | .Lupdate_just_ret: |
135 | ret | 131 | ret |
136 | ENDPROC(clmul_ghash_update) | 132 | ENDPROC(clmul_ghash_update) |
137 | |||
138 | /* | ||
139 | * void clmul_ghash_setkey(be128 *shash, const u8 *key); | ||
140 | * | ||
141 | * Calculate hash_key << 1 mod poly | ||
142 | */ | ||
143 | ENTRY(clmul_ghash_setkey) | ||
144 | movaps .Lbswap_mask, BSWAP | ||
145 | movups (%rsi), %xmm0 | ||
146 | PSHUFB_XMM BSWAP %xmm0 | ||
147 | movaps %xmm0, %xmm1 | ||
148 | psllq $1, %xmm0 | ||
149 | psrlq $63, %xmm1 | ||
150 | movaps %xmm1, %xmm2 | ||
151 | pslldq $8, %xmm1 | ||
152 | psrldq $8, %xmm2 | ||
153 | por %xmm1, %xmm0 | ||
154 | # reduction | ||
155 | pshufd $0b00100100, %xmm2, %xmm1 | ||
156 | pcmpeqd .Ltwo_one, %xmm1 | ||
157 | pand .Lpoly, %xmm1 | ||
158 | pxor %xmm1, %xmm0 | ||
159 | movups %xmm0, (%rdi) | ||
160 | ret | ||
161 | ENDPROC(clmul_ghash_setkey) | ||
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c index 6759dd1135be..d785cf2c529c 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_glue.c +++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c | |||
@@ -30,8 +30,6 @@ void clmul_ghash_mul(char *dst, const be128 *shash); | |||
30 | void clmul_ghash_update(char *dst, const char *src, unsigned int srclen, | 30 | void clmul_ghash_update(char *dst, const char *src, unsigned int srclen, |
31 | const be128 *shash); | 31 | const be128 *shash); |
32 | 32 | ||
33 | void clmul_ghash_setkey(be128 *shash, const u8 *key); | ||
34 | |||
35 | struct ghash_async_ctx { | 33 | struct ghash_async_ctx { |
36 | struct cryptd_ahash *cryptd_tfm; | 34 | struct cryptd_ahash *cryptd_tfm; |
37 | }; | 35 | }; |
@@ -58,13 +56,23 @@ static int ghash_setkey(struct crypto_shash *tfm, | |||
58 | const u8 *key, unsigned int keylen) | 56 | const u8 *key, unsigned int keylen) |
59 | { | 57 | { |
60 | struct ghash_ctx *ctx = crypto_shash_ctx(tfm); | 58 | struct ghash_ctx *ctx = crypto_shash_ctx(tfm); |
59 | be128 *x = (be128 *)key; | ||
60 | u64 a, b; | ||
61 | 61 | ||
62 | if (keylen != GHASH_BLOCK_SIZE) { | 62 | if (keylen != GHASH_BLOCK_SIZE) { |
63 | crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | 63 | crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); |
64 | return -EINVAL; | 64 | return -EINVAL; |
65 | } | 65 | } |
66 | 66 | ||
67 | clmul_ghash_setkey(&ctx->shash, key); | 67 | /* perform multiplication by 'x' in GF(2^128) */ |
68 | a = be64_to_cpu(x->a); | ||
69 | b = be64_to_cpu(x->b); | ||
70 | |||
71 | ctx->shash.a = (__be64)((b << 1) | (a >> 63)); | ||
72 | ctx->shash.b = (__be64)((a << 1) | (b >> 63)); | ||
73 | |||
74 | if (a >> 63) | ||
75 | ctx->shash.b ^= cpu_to_be64(0xc2); | ||
68 | 76 | ||
69 | return 0; | 77 | return 0; |
70 | } | 78 | } |