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