Skip to content

Commit b8d2e7b

Browse files
ebiggersherbertx
authored andcommitted
crypto: x86/aegis128 - eliminate some indirect calls
Instead of using a struct of function pointers to decide whether to call the encryption or decryption assembly functions, use a conditional branch on a bool. Force-inline the functions to avoid actually generating the branch. This improves performance slightly since indirect calls are slow. Remove the now-unnecessary CFI stubs. Note that just force-inlining the existing functions might cause the compiler to optimize out the indirect branches, but that would not be a reliable way to do it and the CFI stubs would still be required. Reviewed-by: Ondrej Mosnacek <[email protected]> Signed-off-by: Eric Biggers <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent ebb445f commit b8d2e7b

File tree

2 files changed

+40
-43
lines changed

2 files changed

+40
-43
lines changed

arch/x86/crypto/aegis128-aesni-asm.S

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
#include <linux/linkage.h>
10-
#include <linux/cfi_types.h>
1110
#include <asm/frame.h>
1211

1312
#define STATE0 %xmm0
@@ -403,7 +402,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_ad)
403402
* void crypto_aegis128_aesni_enc(void *state, unsigned int length,
404403
* const void *src, void *dst);
405404
*/
406-
SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
405+
SYM_FUNC_START(crypto_aegis128_aesni_enc)
407406
FRAME_BEGIN
408407

409408
cmp $0x10, LEN
@@ -500,7 +499,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_enc)
500499
* void crypto_aegis128_aesni_enc_tail(void *state, unsigned int length,
501500
* const void *src, void *dst);
502501
*/
503-
SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail)
502+
SYM_FUNC_START(crypto_aegis128_aesni_enc_tail)
504503
FRAME_BEGIN
505504

506505
/* load the state: */
@@ -557,7 +556,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_enc_tail)
557556
* void crypto_aegis128_aesni_dec(void *state, unsigned int length,
558557
* const void *src, void *dst);
559558
*/
560-
SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
559+
SYM_FUNC_START(crypto_aegis128_aesni_dec)
561560
FRAME_BEGIN
562561

563562
cmp $0x10, LEN
@@ -654,7 +653,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_dec)
654653
* void crypto_aegis128_aesni_dec_tail(void *state, unsigned int length,
655654
* const void *src, void *dst);
656655
*/
657-
SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail)
656+
SYM_FUNC_START(crypto_aegis128_aesni_dec_tail)
658657
FRAME_BEGIN
659658

660659
/* load the state: */

arch/x86/crypto/aegis128-aesni-glue.c

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,6 @@ struct aegis_ctx {
5656
struct aegis_block key;
5757
};
5858

59-
struct aegis_crypt_ops {
60-
int (*skcipher_walk_init)(struct skcipher_walk *walk,
61-
struct aead_request *req, bool atomic);
62-
63-
void (*crypt_blocks)(void *state, unsigned int length, const void *src,
64-
void *dst);
65-
void (*crypt_tail)(void *state, unsigned int length, const void *src,
66-
void *dst);
67-
};
68-
6959
static void crypto_aegis128_aesni_process_ad(
7060
struct aegis_state *state, struct scatterlist *sg_src,
7161
unsigned int assoclen)
@@ -114,20 +104,37 @@ static void crypto_aegis128_aesni_process_ad(
114104
}
115105
}
116106

117-
static void crypto_aegis128_aesni_process_crypt(
118-
struct aegis_state *state, struct skcipher_walk *walk,
119-
const struct aegis_crypt_ops *ops)
107+
static __always_inline void
108+
crypto_aegis128_aesni_process_crypt(struct aegis_state *state,
109+
struct skcipher_walk *walk, bool enc)
120110
{
121111
while (walk->nbytes >= AEGIS128_BLOCK_SIZE) {
122-
ops->crypt_blocks(state,
123-
round_down(walk->nbytes, AEGIS128_BLOCK_SIZE),
124-
walk->src.virt.addr, walk->dst.virt.addr);
112+
if (enc)
113+
crypto_aegis128_aesni_enc(
114+
state,
115+
round_down(walk->nbytes,
116+
AEGIS128_BLOCK_SIZE),
117+
walk->src.virt.addr,
118+
walk->dst.virt.addr);
119+
else
120+
crypto_aegis128_aesni_dec(
121+
state,
122+
round_down(walk->nbytes,
123+
AEGIS128_BLOCK_SIZE),
124+
walk->src.virt.addr,
125+
walk->dst.virt.addr);
125126
skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE);
126127
}
127128

128129
if (walk->nbytes) {
129-
ops->crypt_tail(state, walk->nbytes, walk->src.virt.addr,
130-
walk->dst.virt.addr);
130+
if (enc)
131+
crypto_aegis128_aesni_enc_tail(state, walk->nbytes,
132+
walk->src.virt.addr,
133+
walk->dst.virt.addr);
134+
else
135+
crypto_aegis128_aesni_dec_tail(state, walk->nbytes,
136+
walk->src.virt.addr,
137+
walk->dst.virt.addr);
131138
skcipher_walk_done(walk, 0);
132139
}
133140
}
@@ -162,42 +169,39 @@ static int crypto_aegis128_aesni_setauthsize(struct crypto_aead *tfm,
162169
return 0;
163170
}
164171

165-
static void crypto_aegis128_aesni_crypt(struct aead_request *req,
166-
struct aegis_block *tag_xor,
167-
unsigned int cryptlen,
168-
const struct aegis_crypt_ops *ops)
172+
static __always_inline void
173+
crypto_aegis128_aesni_crypt(struct aead_request *req,
174+
struct aegis_block *tag_xor,
175+
unsigned int cryptlen, bool enc)
169176
{
170177
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
171178
struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm);
172179
struct skcipher_walk walk;
173180
struct aegis_state state;
174181

175-
ops->skcipher_walk_init(&walk, req, true);
182+
if (enc)
183+
skcipher_walk_aead_encrypt(&walk, req, true);
184+
else
185+
skcipher_walk_aead_decrypt(&walk, req, true);
176186

177187
kernel_fpu_begin();
178188

179189
crypto_aegis128_aesni_init(&state, ctx->key.bytes, req->iv);
180190
crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen);
181-
crypto_aegis128_aesni_process_crypt(&state, &walk, ops);
191+
crypto_aegis128_aesni_process_crypt(&state, &walk, enc);
182192
crypto_aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen);
183193

184194
kernel_fpu_end();
185195
}
186196

187197
static int crypto_aegis128_aesni_encrypt(struct aead_request *req)
188198
{
189-
static const struct aegis_crypt_ops OPS = {
190-
.skcipher_walk_init = skcipher_walk_aead_encrypt,
191-
.crypt_blocks = crypto_aegis128_aesni_enc,
192-
.crypt_tail = crypto_aegis128_aesni_enc_tail,
193-
};
194-
195199
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
196200
struct aegis_block tag = {};
197201
unsigned int authsize = crypto_aead_authsize(tfm);
198202
unsigned int cryptlen = req->cryptlen;
199203

200-
crypto_aegis128_aesni_crypt(req, &tag, cryptlen, &OPS);
204+
crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true);
201205

202206
scatterwalk_map_and_copy(tag.bytes, req->dst,
203207
req->assoclen + cryptlen, authsize, 1);
@@ -208,12 +212,6 @@ static int crypto_aegis128_aesni_decrypt(struct aead_request *req)
208212
{
209213
static const struct aegis_block zeros = {};
210214

211-
static const struct aegis_crypt_ops OPS = {
212-
.skcipher_walk_init = skcipher_walk_aead_decrypt,
213-
.crypt_blocks = crypto_aegis128_aesni_dec,
214-
.crypt_tail = crypto_aegis128_aesni_dec_tail,
215-
};
216-
217215
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
218216
struct aegis_block tag;
219217
unsigned int authsize = crypto_aead_authsize(tfm);
@@ -222,7 +220,7 @@ static int crypto_aegis128_aesni_decrypt(struct aead_request *req)
222220
scatterwalk_map_and_copy(tag.bytes, req->src,
223221
req->assoclen + cryptlen, authsize, 0);
224222

225-
crypto_aegis128_aesni_crypt(req, &tag, cryptlen, &OPS);
223+
crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false);
226224

227225
return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0;
228226
}

0 commit comments

Comments
 (0)