crypto: cipher - remove crt_u.cipher (struct cipher_tfm)
Of the three fields in crt_u.cipher (struct cipher_tfm), ->cit_setkey() is pointless because it always points to setkey() in crypto/cipher.c. ->cit_decrypt_one() and ->cit_encrypt_one() are slightly less pointless, since if the algorithm doesn't have an alignmask, they are set directly to ->cia_encrypt() and ->cia_decrypt(). However, this "optimization" isn't worthwhile because: - The "cipher" algorithm type is the only algorithm still using crt_u, so it's bloating every struct crypto_tfm for every algorithm type. - If the algorithm has an alignmask, this "optimization" actually makes things slower, as it causes 2 indirect calls per block rather than 1. - It adds extra code complexity. - Some templates already call ->cia_encrypt()/->cia_decrypt() directly instead of going through ->cit_encrypt_one()/->cit_decrypt_one(). - The "cipher" algorithm type never gives optimal performance anyway. For that, a higher-level type such as skcipher needs to be used. Therefore, just remove the extra indirection, and make crypto_cipher_setkey(), crypto_cipher_encrypt_one(), and crypto_cipher_decrypt_one() be direct calls into crypto/cipher.c. Also remove the unused function crypto_cipher_cast(). Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* Cipher operations.
|
||||
* Single-block cipher operations.
|
||||
*
|
||||
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
|
||||
* Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
|
||||
@@ -16,11 +16,11 @@
|
||||
#include <linux/string.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
|
||||
static int setkey_unaligned(struct crypto_cipher *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
struct cipher_alg *cia = crypto_cipher_alg(tfm);
|
||||
unsigned long alignmask = crypto_cipher_alignmask(tfm);
|
||||
int ret;
|
||||
u8 *buffer, *alignbuffer;
|
||||
unsigned long absize;
|
||||
@@ -32,83 +32,63 @@ static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
|
||||
|
||||
alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||
memcpy(alignbuffer, key, keylen);
|
||||
ret = cia->cia_setkey(tfm, alignbuffer, keylen);
|
||||
ret = cia->cia_setkey(crypto_cipher_tfm(tfm), alignbuffer, keylen);
|
||||
memset(alignbuffer, 0, keylen);
|
||||
kfree(buffer);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
int crypto_cipher_setkey(struct crypto_cipher *tfm,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
struct cipher_alg *cia = crypto_cipher_alg(tfm);
|
||||
unsigned long alignmask = crypto_cipher_alignmask(tfm);
|
||||
|
||||
tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
|
||||
crypto_cipher_clear_flags(tfm, CRYPTO_TFM_RES_MASK);
|
||||
if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
|
||||
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
|
||||
crypto_cipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((unsigned long)key & alignmask)
|
||||
return setkey_unaligned(tfm, key, keylen);
|
||||
|
||||
return cia->cia_setkey(tfm, key, keylen);
|
||||
return cia->cia_setkey(crypto_cipher_tfm(tfm), key, keylen);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_cipher_setkey);
|
||||
|
||||
static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
|
||||
const u8 *),
|
||||
struct crypto_tfm *tfm,
|
||||
u8 *dst, const u8 *src)
|
||||
static inline void cipher_crypt_one(struct crypto_cipher *tfm,
|
||||
u8 *dst, const u8 *src, bool enc)
|
||||
{
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
unsigned int size = crypto_tfm_alg_blocksize(tfm);
|
||||
u8 buffer[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK];
|
||||
u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||
|
||||
memcpy(tmp, src, size);
|
||||
fn(tfm, tmp, tmp);
|
||||
memcpy(dst, tmp, size);
|
||||
}
|
||||
|
||||
static void cipher_encrypt_unaligned(struct crypto_tfm *tfm,
|
||||
u8 *dst, const u8 *src)
|
||||
{
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
|
||||
unsigned long alignmask = crypto_cipher_alignmask(tfm);
|
||||
struct cipher_alg *cia = crypto_cipher_alg(tfm);
|
||||
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
|
||||
enc ? cia->cia_encrypt : cia->cia_decrypt;
|
||||
|
||||
if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
|
||||
cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src);
|
||||
return;
|
||||
unsigned int bs = crypto_cipher_blocksize(tfm);
|
||||
u8 buffer[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK];
|
||||
u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||
|
||||
memcpy(tmp, src, bs);
|
||||
fn(crypto_cipher_tfm(tfm), tmp, tmp);
|
||||
memcpy(dst, tmp, bs);
|
||||
} else {
|
||||
fn(crypto_cipher_tfm(tfm), dst, src);
|
||||
}
|
||||
|
||||
cipher->cia_encrypt(tfm, dst, src);
|
||||
}
|
||||
|
||||
static void cipher_decrypt_unaligned(struct crypto_tfm *tfm,
|
||||
u8 *dst, const u8 *src)
|
||||
void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
|
||||
u8 *dst, const u8 *src)
|
||||
{
|
||||
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||
struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
|
||||
|
||||
if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
|
||||
cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src);
|
||||
return;
|
||||
}
|
||||
|
||||
cipher->cia_decrypt(tfm, dst, src);
|
||||
cipher_crypt_one(tfm, dst, src, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_cipher_encrypt_one);
|
||||
|
||||
int crypto_init_cipher_ops(struct crypto_tfm *tfm)
|
||||
void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
|
||||
u8 *dst, const u8 *src)
|
||||
{
|
||||
struct cipher_tfm *ops = &tfm->crt_cipher;
|
||||
struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
|
||||
|
||||
ops->cit_setkey = setkey;
|
||||
ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ?
|
||||
cipher_encrypt_unaligned : cipher->cia_encrypt;
|
||||
ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
|
||||
cipher_decrypt_unaligned : cipher->cia_decrypt;
|
||||
|
||||
return 0;
|
||||
cipher_crypt_one(tfm, dst, src, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_cipher_decrypt_one);
|
||||
|
Reference in New Issue
Block a user