xref: /openbmc/linux/crypto/cipher.c (revision c774e93e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Cryptographic API.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Cipher operations.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
7*c774e93eSHerbert Xu  * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify it
101da177e4SLinus Torvalds  * under the terms of the GNU General Public License as published by the Free
111da177e4SLinus Torvalds  * Software Foundation; either version 2 of the License, or (at your option)
121da177e4SLinus Torvalds  * any later version.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds #include <linux/compiler.h>
161da177e4SLinus Torvalds #include <linux/kernel.h>
171da177e4SLinus Torvalds #include <linux/crypto.h>
181da177e4SLinus Torvalds #include <linux/errno.h>
191da177e4SLinus Torvalds #include <linux/mm.h>
201da177e4SLinus Torvalds #include <linux/slab.h>
211da177e4SLinus Torvalds #include <linux/string.h>
221da177e4SLinus Torvalds #include <asm/scatterlist.h>
231da177e4SLinus Torvalds #include "internal.h"
241da177e4SLinus Torvalds #include "scatterwalk.h"
251da177e4SLinus Torvalds 
26*c774e93eSHerbert Xu struct cipher_desc {
27*c774e93eSHerbert Xu 	struct crypto_tfm *tfm;
28*c774e93eSHerbert Xu 	void (*crfn)(void *ctx, u8 *dst, const u8 *src);
29*c774e93eSHerbert Xu 	unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst,
30*c774e93eSHerbert Xu 			     const u8 *src, unsigned int nbytes);
31*c774e93eSHerbert Xu 	void *info;
32*c774e93eSHerbert Xu };
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds static inline void xor_64(u8 *a, const u8 *b)
351da177e4SLinus Torvalds {
361da177e4SLinus Torvalds 	((u32 *)a)[0] ^= ((u32 *)b)[0];
371da177e4SLinus Torvalds 	((u32 *)a)[1] ^= ((u32 *)b)[1];
381da177e4SLinus Torvalds }
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds static inline void xor_128(u8 *a, const u8 *b)
411da177e4SLinus Torvalds {
421da177e4SLinus Torvalds 	((u32 *)a)[0] ^= ((u32 *)b)[0];
431da177e4SLinus Torvalds 	((u32 *)a)[1] ^= ((u32 *)b)[1];
441da177e4SLinus Torvalds 	((u32 *)a)[2] ^= ((u32 *)b)[2];
451da177e4SLinus Torvalds 	((u32 *)a)[3] ^= ((u32 *)b)[3];
461da177e4SLinus Torvalds }
471da177e4SLinus Torvalds 
48*c774e93eSHerbert Xu static unsigned int crypt_slow(const struct cipher_desc *desc,
49*c774e93eSHerbert Xu 			       struct scatter_walk *in,
50*c774e93eSHerbert Xu 			       struct scatter_walk *out, unsigned int bsize)
511da177e4SLinus Torvalds {
52*c774e93eSHerbert Xu 	u8 src[bsize];
53*c774e93eSHerbert Xu 	u8 dst[bsize];
54*c774e93eSHerbert Xu 	unsigned int n;
551da177e4SLinus Torvalds 
56*c774e93eSHerbert Xu 	n = scatterwalk_copychunks(src, in, bsize, 0);
57*c774e93eSHerbert Xu 	scatterwalk_advance(in, n);
58*c774e93eSHerbert Xu 
59*c774e93eSHerbert Xu 	desc->prfn(desc, dst, src, bsize);
60*c774e93eSHerbert Xu 
61*c774e93eSHerbert Xu 	n = scatterwalk_copychunks(dst, out, bsize, 1);
62*c774e93eSHerbert Xu 	scatterwalk_advance(out, n);
63*c774e93eSHerbert Xu 
64*c774e93eSHerbert Xu 	return bsize;
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds 
67*c774e93eSHerbert Xu static inline unsigned int crypt_fast(const struct cipher_desc *desc,
68*c774e93eSHerbert Xu 				      struct scatter_walk *in,
69*c774e93eSHerbert Xu 				      struct scatter_walk *out,
70*c774e93eSHerbert Xu 				      unsigned int nbytes)
711da177e4SLinus Torvalds {
72*c774e93eSHerbert Xu 	u8 *src, *dst;
731da177e4SLinus Torvalds 
74*c774e93eSHerbert Xu 	src = in->data;
75*c774e93eSHerbert Xu 	dst = scatterwalk_samebuf(in, out) ? src : out->data;
761da177e4SLinus Torvalds 
77*c774e93eSHerbert Xu 	nbytes = desc->prfn(desc, dst, src, nbytes);
781da177e4SLinus Torvalds 
79*c774e93eSHerbert Xu 	scatterwalk_advance(in, nbytes);
80*c774e93eSHerbert Xu 	scatterwalk_advance(out, nbytes);
811da177e4SLinus Torvalds 
82*c774e93eSHerbert Xu 	return nbytes;
831da177e4SLinus Torvalds }
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds /*
861da177e4SLinus Torvalds  * Generic encrypt/decrypt wrapper for ciphers, handles operations across
871da177e4SLinus Torvalds  * multiple page boundaries by using temporary blocks.  In user context,
88*c774e93eSHerbert Xu  * the kernel is given a chance to schedule us once per page.
891da177e4SLinus Torvalds  */
90*c774e93eSHerbert Xu static int crypt(const struct cipher_desc *desc,
911da177e4SLinus Torvalds 		 struct scatterlist *dst,
921da177e4SLinus Torvalds 		 struct scatterlist *src,
93*c774e93eSHerbert Xu 		 unsigned int nbytes)
941da177e4SLinus Torvalds {
951da177e4SLinus Torvalds 	struct scatter_walk walk_in, walk_out;
96*c774e93eSHerbert Xu 	struct crypto_tfm *tfm = desc->tfm;
971da177e4SLinus Torvalds 	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	if (!nbytes)
1001da177e4SLinus Torvalds 		return 0;
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds 	if (nbytes % bsize) {
1031da177e4SLinus Torvalds 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
1041da177e4SLinus Torvalds 		return -EINVAL;
1051da177e4SLinus Torvalds 	}
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 	scatterwalk_start(&walk_in, src);
1081da177e4SLinus Torvalds 	scatterwalk_start(&walk_out, dst);
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	for(;;) {
111*c774e93eSHerbert Xu 		unsigned int n;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 		scatterwalk_map(&walk_in, 0);
1141da177e4SLinus Torvalds 		scatterwalk_map(&walk_out, 1);
1151da177e4SLinus Torvalds 
116*c774e93eSHerbert Xu 		n = scatterwalk_clamp(&walk_in, nbytes);
117*c774e93eSHerbert Xu 		n = scatterwalk_clamp(&walk_out, n);
1181da177e4SLinus Torvalds 
119*c774e93eSHerbert Xu 		if (likely(n >= bsize))
120*c774e93eSHerbert Xu 			n = crypt_fast(desc, &walk_in, &walk_out, n);
121*c774e93eSHerbert Xu 		else
122*c774e93eSHerbert Xu 			n = crypt_slow(desc, &walk_in, &walk_out, bsize);
1231da177e4SLinus Torvalds 
124*c774e93eSHerbert Xu 		nbytes -= n;
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds 		scatterwalk_done(&walk_in, 0, nbytes);
1271da177e4SLinus Torvalds 		scatterwalk_done(&walk_out, 1, nbytes);
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 		if (!nbytes)
1301da177e4SLinus Torvalds 			return 0;
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 		crypto_yield(tfm);
1331da177e4SLinus Torvalds 	}
1341da177e4SLinus Torvalds }
1351da177e4SLinus Torvalds 
136*c774e93eSHerbert Xu static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
137*c774e93eSHerbert Xu 					u8 *dst, const u8 *src,
138*c774e93eSHerbert Xu 					unsigned int nbytes)
1391da177e4SLinus Torvalds {
140*c774e93eSHerbert Xu 	struct crypto_tfm *tfm = desc->tfm;
141*c774e93eSHerbert Xu 	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
142*c774e93eSHerbert Xu 	int bsize = crypto_tfm_alg_blocksize(tfm);
1431da177e4SLinus Torvalds 
144*c774e93eSHerbert Xu 	void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
145*c774e93eSHerbert Xu 	u8 *iv = desc->info;
146*c774e93eSHerbert Xu 	unsigned int done = 0;
147*c774e93eSHerbert Xu 
148*c774e93eSHerbert Xu 	do {
149*c774e93eSHerbert Xu 		xor(iv, src);
1501da177e4SLinus Torvalds 		fn(crypto_tfm_ctx(tfm), dst, iv);
151*c774e93eSHerbert Xu 		memcpy(iv, dst, bsize);
152*c774e93eSHerbert Xu 
153*c774e93eSHerbert Xu 		src += bsize;
154*c774e93eSHerbert Xu 		dst += bsize;
155*c774e93eSHerbert Xu 	} while ((done += bsize) < nbytes);
156*c774e93eSHerbert Xu 
157*c774e93eSHerbert Xu 	return done;
1581da177e4SLinus Torvalds }
1591da177e4SLinus Torvalds 
160*c774e93eSHerbert Xu static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
161*c774e93eSHerbert Xu 					u8 *dst, const u8 *src,
162*c774e93eSHerbert Xu 					unsigned int nbytes)
1631da177e4SLinus Torvalds {
164*c774e93eSHerbert Xu 	struct crypto_tfm *tfm = desc->tfm;
165*c774e93eSHerbert Xu 	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
166*c774e93eSHerbert Xu 	int bsize = crypto_tfm_alg_blocksize(tfm);
1671da177e4SLinus Torvalds 
168*c774e93eSHerbert Xu 	u8 stack[src == dst ? bsize : 0];
169*c774e93eSHerbert Xu 	u8 *buf = stack;
170*c774e93eSHerbert Xu 	u8 **dst_p = src == dst ? &buf : &dst;
171*c774e93eSHerbert Xu 
172*c774e93eSHerbert Xu 	void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
173*c774e93eSHerbert Xu 	u8 *iv = desc->info;
174*c774e93eSHerbert Xu 	unsigned int done = 0;
175*c774e93eSHerbert Xu 
176*c774e93eSHerbert Xu 	do {
177*c774e93eSHerbert Xu 		u8 *tmp_dst = *dst_p;
178*c774e93eSHerbert Xu 
179*c774e93eSHerbert Xu 		fn(crypto_tfm_ctx(tfm), tmp_dst, src);
180*c774e93eSHerbert Xu 		xor(tmp_dst, iv);
181*c774e93eSHerbert Xu 		memcpy(iv, src, bsize);
182*c774e93eSHerbert Xu 		if (tmp_dst != dst)
183*c774e93eSHerbert Xu 			memcpy(dst, tmp_dst, bsize);
184*c774e93eSHerbert Xu 
185*c774e93eSHerbert Xu 		src += bsize;
186*c774e93eSHerbert Xu 		dst += bsize;
187*c774e93eSHerbert Xu 	} while ((done += bsize) < nbytes);
188*c774e93eSHerbert Xu 
189*c774e93eSHerbert Xu 	return done;
1901da177e4SLinus Torvalds }
1911da177e4SLinus Torvalds 
192*c774e93eSHerbert Xu static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
193*c774e93eSHerbert Xu 				const u8 *src, unsigned int nbytes)
1941da177e4SLinus Torvalds {
195*c774e93eSHerbert Xu 	struct crypto_tfm *tfm = desc->tfm;
196*c774e93eSHerbert Xu 	int bsize = crypto_tfm_alg_blocksize(tfm);
197*c774e93eSHerbert Xu 	void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
198*c774e93eSHerbert Xu 	unsigned int done = 0;
199*c774e93eSHerbert Xu 
200*c774e93eSHerbert Xu 	do {
2011da177e4SLinus Torvalds 		fn(crypto_tfm_ctx(tfm), dst, src);
202*c774e93eSHerbert Xu 
203*c774e93eSHerbert Xu 		src += bsize;
204*c774e93eSHerbert Xu 		dst += bsize;
205*c774e93eSHerbert Xu 	} while ((done += bsize) < nbytes);
206*c774e93eSHerbert Xu 
207*c774e93eSHerbert Xu 	return done;
2081da177e4SLinus Torvalds }
2091da177e4SLinus Torvalds 
2101da177e4SLinus Torvalds static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
2131da177e4SLinus Torvalds 
2141da177e4SLinus Torvalds 	if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
2151da177e4SLinus Torvalds 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
2161da177e4SLinus Torvalds 		return -EINVAL;
2171da177e4SLinus Torvalds 	} else
2181da177e4SLinus Torvalds 		return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
2191da177e4SLinus Torvalds 		                       &tfm->crt_flags);
2201da177e4SLinus Torvalds }
2211da177e4SLinus Torvalds 
2221da177e4SLinus Torvalds static int ecb_encrypt(struct crypto_tfm *tfm,
2231da177e4SLinus Torvalds 		       struct scatterlist *dst,
2241da177e4SLinus Torvalds                        struct scatterlist *src, unsigned int nbytes)
2251da177e4SLinus Torvalds {
226*c774e93eSHerbert Xu 	struct cipher_desc desc;
227*c774e93eSHerbert Xu 
228*c774e93eSHerbert Xu 	desc.tfm = tfm;
229*c774e93eSHerbert Xu 	desc.crfn = tfm->__crt_alg->cra_cipher.cia_encrypt;
230*c774e93eSHerbert Xu 	desc.prfn = ecb_process;
231*c774e93eSHerbert Xu 
232*c774e93eSHerbert Xu 	return crypt(&desc, dst, src, nbytes);
2331da177e4SLinus Torvalds }
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds static int ecb_decrypt(struct crypto_tfm *tfm,
2361da177e4SLinus Torvalds                        struct scatterlist *dst,
2371da177e4SLinus Torvalds                        struct scatterlist *src,
2381da177e4SLinus Torvalds 		       unsigned int nbytes)
2391da177e4SLinus Torvalds {
240*c774e93eSHerbert Xu 	struct cipher_desc desc;
241*c774e93eSHerbert Xu 
242*c774e93eSHerbert Xu 	desc.tfm = tfm;
243*c774e93eSHerbert Xu 	desc.crfn = tfm->__crt_alg->cra_cipher.cia_decrypt;
244*c774e93eSHerbert Xu 	desc.prfn = ecb_process;
245*c774e93eSHerbert Xu 
246*c774e93eSHerbert Xu 	return crypt(&desc, dst, src, nbytes);
2471da177e4SLinus Torvalds }
2481da177e4SLinus Torvalds 
2491da177e4SLinus Torvalds static int cbc_encrypt(struct crypto_tfm *tfm,
2501da177e4SLinus Torvalds                        struct scatterlist *dst,
2511da177e4SLinus Torvalds                        struct scatterlist *src,
2521da177e4SLinus Torvalds 		       unsigned int nbytes)
2531da177e4SLinus Torvalds {
254*c774e93eSHerbert Xu 	struct cipher_desc desc;
255*c774e93eSHerbert Xu 
256*c774e93eSHerbert Xu 	desc.tfm = tfm;
257*c774e93eSHerbert Xu 	desc.crfn = tfm->__crt_alg->cra_cipher.cia_encrypt;
258*c774e93eSHerbert Xu 	desc.prfn = cbc_process_encrypt;
259*c774e93eSHerbert Xu 	desc.info = tfm->crt_cipher.cit_iv;
260*c774e93eSHerbert Xu 
261*c774e93eSHerbert Xu 	return crypt(&desc, dst, src, nbytes);
2621da177e4SLinus Torvalds }
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds static int cbc_encrypt_iv(struct crypto_tfm *tfm,
2651da177e4SLinus Torvalds                           struct scatterlist *dst,
2661da177e4SLinus Torvalds                           struct scatterlist *src,
2671da177e4SLinus Torvalds                           unsigned int nbytes, u8 *iv)
2681da177e4SLinus Torvalds {
269*c774e93eSHerbert Xu 	struct cipher_desc desc;
270*c774e93eSHerbert Xu 
271*c774e93eSHerbert Xu 	desc.tfm = tfm;
272*c774e93eSHerbert Xu 	desc.crfn = tfm->__crt_alg->cra_cipher.cia_encrypt;
273*c774e93eSHerbert Xu 	desc.prfn = cbc_process_encrypt;
274*c774e93eSHerbert Xu 	desc.info = iv;
275*c774e93eSHerbert Xu 
276*c774e93eSHerbert Xu 	return crypt(&desc, dst, src, nbytes);
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds 
2791da177e4SLinus Torvalds static int cbc_decrypt(struct crypto_tfm *tfm,
2801da177e4SLinus Torvalds                        struct scatterlist *dst,
2811da177e4SLinus Torvalds                        struct scatterlist *src,
2821da177e4SLinus Torvalds 		       unsigned int nbytes)
2831da177e4SLinus Torvalds {
284*c774e93eSHerbert Xu 	struct cipher_desc desc;
285*c774e93eSHerbert Xu 
286*c774e93eSHerbert Xu 	desc.tfm = tfm;
287*c774e93eSHerbert Xu 	desc.crfn = tfm->__crt_alg->cra_cipher.cia_decrypt;
288*c774e93eSHerbert Xu 	desc.prfn = cbc_process_decrypt;
289*c774e93eSHerbert Xu 	desc.info = tfm->crt_cipher.cit_iv;
290*c774e93eSHerbert Xu 
291*c774e93eSHerbert Xu 	return crypt(&desc, dst, src, nbytes);
2921da177e4SLinus Torvalds }
2931da177e4SLinus Torvalds 
2941da177e4SLinus Torvalds static int cbc_decrypt_iv(struct crypto_tfm *tfm,
2951da177e4SLinus Torvalds                           struct scatterlist *dst,
2961da177e4SLinus Torvalds                           struct scatterlist *src,
2971da177e4SLinus Torvalds                           unsigned int nbytes, u8 *iv)
2981da177e4SLinus Torvalds {
299*c774e93eSHerbert Xu 	struct cipher_desc desc;
300*c774e93eSHerbert Xu 
301*c774e93eSHerbert Xu 	desc.tfm = tfm;
302*c774e93eSHerbert Xu 	desc.crfn = tfm->__crt_alg->cra_cipher.cia_decrypt;
303*c774e93eSHerbert Xu 	desc.prfn = cbc_process_decrypt;
304*c774e93eSHerbert Xu 	desc.info = iv;
305*c774e93eSHerbert Xu 
306*c774e93eSHerbert Xu 	return crypt(&desc, dst, src, nbytes);
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds 
3091da177e4SLinus Torvalds static int nocrypt(struct crypto_tfm *tfm,
3101da177e4SLinus Torvalds                    struct scatterlist *dst,
3111da177e4SLinus Torvalds                    struct scatterlist *src,
3121da177e4SLinus Torvalds 		   unsigned int nbytes)
3131da177e4SLinus Torvalds {
3141da177e4SLinus Torvalds 	return -ENOSYS;
3151da177e4SLinus Torvalds }
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds static int nocrypt_iv(struct crypto_tfm *tfm,
3181da177e4SLinus Torvalds                       struct scatterlist *dst,
3191da177e4SLinus Torvalds                       struct scatterlist *src,
3201da177e4SLinus Torvalds                       unsigned int nbytes, u8 *iv)
3211da177e4SLinus Torvalds {
3221da177e4SLinus Torvalds 	return -ENOSYS;
3231da177e4SLinus Torvalds }
3241da177e4SLinus Torvalds 
3251da177e4SLinus Torvalds int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
3261da177e4SLinus Torvalds {
3271da177e4SLinus Torvalds 	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds 	tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
3301da177e4SLinus Torvalds 	if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
3311da177e4SLinus Torvalds 		tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds 	return 0;
3341da177e4SLinus Torvalds }
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds int crypto_init_cipher_ops(struct crypto_tfm *tfm)
3371da177e4SLinus Torvalds {
3381da177e4SLinus Torvalds 	int ret = 0;
3391da177e4SLinus Torvalds 	struct cipher_tfm *ops = &tfm->crt_cipher;
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds 	ops->cit_setkey = setkey;
3421da177e4SLinus Torvalds 
3431da177e4SLinus Torvalds 	switch (tfm->crt_cipher.cit_mode) {
3441da177e4SLinus Torvalds 	case CRYPTO_TFM_MODE_ECB:
3451da177e4SLinus Torvalds 		ops->cit_encrypt = ecb_encrypt;
3461da177e4SLinus Torvalds 		ops->cit_decrypt = ecb_decrypt;
3471da177e4SLinus Torvalds 		break;
3481da177e4SLinus Torvalds 
3491da177e4SLinus Torvalds 	case CRYPTO_TFM_MODE_CBC:
3501da177e4SLinus Torvalds 		ops->cit_encrypt = cbc_encrypt;
3511da177e4SLinus Torvalds 		ops->cit_decrypt = cbc_decrypt;
3521da177e4SLinus Torvalds 		ops->cit_encrypt_iv = cbc_encrypt_iv;
3531da177e4SLinus Torvalds 		ops->cit_decrypt_iv = cbc_decrypt_iv;
3541da177e4SLinus Torvalds 		break;
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds 	case CRYPTO_TFM_MODE_CFB:
3571da177e4SLinus Torvalds 		ops->cit_encrypt = nocrypt;
3581da177e4SLinus Torvalds 		ops->cit_decrypt = nocrypt;
3591da177e4SLinus Torvalds 		ops->cit_encrypt_iv = nocrypt_iv;
3601da177e4SLinus Torvalds 		ops->cit_decrypt_iv = nocrypt_iv;
3611da177e4SLinus Torvalds 		break;
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 	case CRYPTO_TFM_MODE_CTR:
3641da177e4SLinus Torvalds 		ops->cit_encrypt = nocrypt;
3651da177e4SLinus Torvalds 		ops->cit_decrypt = nocrypt;
3661da177e4SLinus Torvalds 		ops->cit_encrypt_iv = nocrypt_iv;
3671da177e4SLinus Torvalds 		ops->cit_decrypt_iv = nocrypt_iv;
3681da177e4SLinus Torvalds 		break;
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds 	default:
3711da177e4SLinus Torvalds 		BUG();
3721da177e4SLinus Torvalds 	}
3731da177e4SLinus Torvalds 
3741da177e4SLinus Torvalds 	if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
3751da177e4SLinus Torvalds 
3761da177e4SLinus Torvalds 	    	switch (crypto_tfm_alg_blocksize(tfm)) {
3771da177e4SLinus Torvalds 	    	case 8:
3781da177e4SLinus Torvalds 	    		ops->cit_xor_block = xor_64;
3791da177e4SLinus Torvalds 	    		break;
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds 	    	case 16:
3821da177e4SLinus Torvalds 	    		ops->cit_xor_block = xor_128;
3831da177e4SLinus Torvalds 	    		break;
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	    	default:
3861da177e4SLinus Torvalds 	    		printk(KERN_WARNING "%s: block size %u not supported\n",
3871da177e4SLinus Torvalds 	    		       crypto_tfm_alg_name(tfm),
3881da177e4SLinus Torvalds 	    		       crypto_tfm_alg_blocksize(tfm));
3891da177e4SLinus Torvalds 	    		ret = -EINVAL;
3901da177e4SLinus Torvalds 	    		goto out;
3911da177e4SLinus Torvalds 	    	}
3921da177e4SLinus Torvalds 
3931da177e4SLinus Torvalds 		ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
3941da177e4SLinus Torvalds 	    	ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
3951da177e4SLinus Torvalds 		if (ops->cit_iv == NULL)
3961da177e4SLinus Torvalds 			ret = -ENOMEM;
3971da177e4SLinus Torvalds 	}
3981da177e4SLinus Torvalds 
3991da177e4SLinus Torvalds out:
4001da177e4SLinus Torvalds 	return ret;
4011da177e4SLinus Torvalds }
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
4041da177e4SLinus Torvalds {
4051da177e4SLinus Torvalds 	kfree(tfm->crt_cipher.cit_iv);
4061da177e4SLinus Torvalds }
407