0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <crypto/algapi.h>
0012 #include <crypto/internal/cipher.h>
0013 #include <linux/kernel.h>
0014 #include <linux/crypto.h>
0015 #include <linux/errno.h>
0016 #include <linux/slab.h>
0017 #include <linux/string.h>
0018 #include "internal.h"
0019
0020 static int setkey_unaligned(struct crypto_cipher *tfm, const u8 *key,
0021 unsigned int keylen)
0022 {
0023 struct cipher_alg *cia = crypto_cipher_alg(tfm);
0024 unsigned long alignmask = crypto_cipher_alignmask(tfm);
0025 int ret;
0026 u8 *buffer, *alignbuffer;
0027 unsigned long absize;
0028
0029 absize = keylen + alignmask;
0030 buffer = kmalloc(absize, GFP_ATOMIC);
0031 if (!buffer)
0032 return -ENOMEM;
0033
0034 alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
0035 memcpy(alignbuffer, key, keylen);
0036 ret = cia->cia_setkey(crypto_cipher_tfm(tfm), alignbuffer, keylen);
0037 memset(alignbuffer, 0, keylen);
0038 kfree(buffer);
0039 return ret;
0040
0041 }
0042
0043 int crypto_cipher_setkey(struct crypto_cipher *tfm,
0044 const u8 *key, unsigned int keylen)
0045 {
0046 struct cipher_alg *cia = crypto_cipher_alg(tfm);
0047 unsigned long alignmask = crypto_cipher_alignmask(tfm);
0048
0049 if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize)
0050 return -EINVAL;
0051
0052 if ((unsigned long)key & alignmask)
0053 return setkey_unaligned(tfm, key, keylen);
0054
0055 return cia->cia_setkey(crypto_cipher_tfm(tfm), key, keylen);
0056 }
0057 EXPORT_SYMBOL_NS_GPL(crypto_cipher_setkey, CRYPTO_INTERNAL);
0058
0059 static inline void cipher_crypt_one(struct crypto_cipher *tfm,
0060 u8 *dst, const u8 *src, bool enc)
0061 {
0062 unsigned long alignmask = crypto_cipher_alignmask(tfm);
0063 struct cipher_alg *cia = crypto_cipher_alg(tfm);
0064 void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
0065 enc ? cia->cia_encrypt : cia->cia_decrypt;
0066
0067 if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
0068 unsigned int bs = crypto_cipher_blocksize(tfm);
0069 u8 buffer[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK];
0070 u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
0071
0072 memcpy(tmp, src, bs);
0073 fn(crypto_cipher_tfm(tfm), tmp, tmp);
0074 memcpy(dst, tmp, bs);
0075 } else {
0076 fn(crypto_cipher_tfm(tfm), dst, src);
0077 }
0078 }
0079
0080 void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
0081 u8 *dst, const u8 *src)
0082 {
0083 cipher_crypt_one(tfm, dst, src, true);
0084 }
0085 EXPORT_SYMBOL_NS_GPL(crypto_cipher_encrypt_one, CRYPTO_INTERNAL);
0086
0087 void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
0088 u8 *dst, const u8 *src)
0089 {
0090 cipher_crypt_one(tfm, dst, src, false);
0091 }
0092 EXPORT_SYMBOL_NS_GPL(crypto_cipher_decrypt_one, CRYPTO_INTERNAL);