176cb9521SKevin Coffman /* 276cb9521SKevin Coffman * CTS: Cipher Text Stealing mode 376cb9521SKevin Coffman * 476cb9521SKevin Coffman * COPYRIGHT (c) 2008 576cb9521SKevin Coffman * The Regents of the University of Michigan 676cb9521SKevin Coffman * ALL RIGHTS RESERVED 776cb9521SKevin Coffman * 876cb9521SKevin Coffman * Permission is granted to use, copy, create derivative works 976cb9521SKevin Coffman * and redistribute this software and such derivative works 1076cb9521SKevin Coffman * for any purpose, so long as the name of The University of 1176cb9521SKevin Coffman * Michigan is not used in any advertising or publicity 1276cb9521SKevin Coffman * pertaining to the use of distribution of this software 1376cb9521SKevin Coffman * without specific, written prior authorization. If the 1476cb9521SKevin Coffman * above copyright notice or any other identification of the 1576cb9521SKevin Coffman * University of Michigan is included in any copy of any 1676cb9521SKevin Coffman * portion of this software, then the disclaimer below must 1776cb9521SKevin Coffman * also be included. 1876cb9521SKevin Coffman * 1976cb9521SKevin Coffman * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 2076cb9521SKevin Coffman * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 2176cb9521SKevin Coffman * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 2276cb9521SKevin Coffman * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 2376cb9521SKevin Coffman * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 2476cb9521SKevin Coffman * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 2576cb9521SKevin Coffman * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 2676cb9521SKevin Coffman * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 2776cb9521SKevin Coffman * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 2876cb9521SKevin Coffman * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 2976cb9521SKevin Coffman * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 3076cb9521SKevin Coffman * SUCH DAMAGES. 3176cb9521SKevin Coffman */ 3276cb9521SKevin Coffman 3376cb9521SKevin Coffman /* Derived from various: 3476cb9521SKevin Coffman * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 3576cb9521SKevin Coffman */ 3676cb9521SKevin Coffman 3776cb9521SKevin Coffman /* 3876cb9521SKevin Coffman * This is the Cipher Text Stealing mode as described by 3976cb9521SKevin Coffman * Section 8 of rfc2040 and referenced by rfc3962. 4076cb9521SKevin Coffman * rfc3962 includes errata information in its Appendix A. 4176cb9521SKevin Coffman */ 4276cb9521SKevin Coffman 4376cb9521SKevin Coffman #include <crypto/algapi.h> 4476cb9521SKevin Coffman #include <linux/err.h> 4576cb9521SKevin Coffman #include <linux/init.h> 4676cb9521SKevin Coffman #include <linux/kernel.h> 4776cb9521SKevin Coffman #include <linux/log2.h> 4876cb9521SKevin Coffman #include <linux/module.h> 4976cb9521SKevin Coffman #include <linux/scatterlist.h> 5076cb9521SKevin Coffman #include <crypto/scatterwalk.h> 5176cb9521SKevin Coffman #include <linux/slab.h> 5276cb9521SKevin Coffman 5376cb9521SKevin Coffman struct crypto_cts_ctx { 5476cb9521SKevin Coffman struct crypto_blkcipher *child; 5576cb9521SKevin Coffman }; 5676cb9521SKevin Coffman 5776cb9521SKevin Coffman static int crypto_cts_setkey(struct crypto_tfm *parent, const u8 *key, 5876cb9521SKevin Coffman unsigned int keylen) 5976cb9521SKevin Coffman { 6076cb9521SKevin Coffman struct crypto_cts_ctx *ctx = crypto_tfm_ctx(parent); 6176cb9521SKevin Coffman struct crypto_blkcipher *child = ctx->child; 6276cb9521SKevin Coffman int err; 6376cb9521SKevin Coffman 6476cb9521SKevin Coffman crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 6576cb9521SKevin Coffman crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) & 6676cb9521SKevin Coffman CRYPTO_TFM_REQ_MASK); 6776cb9521SKevin Coffman err = crypto_blkcipher_setkey(child, key, keylen); 6876cb9521SKevin Coffman crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) & 6976cb9521SKevin Coffman CRYPTO_TFM_RES_MASK); 7076cb9521SKevin Coffman return err; 7176cb9521SKevin Coffman } 7276cb9521SKevin Coffman 7376cb9521SKevin Coffman static int cts_cbc_encrypt(struct crypto_cts_ctx *ctx, 7476cb9521SKevin Coffman struct blkcipher_desc *desc, 7576cb9521SKevin Coffman struct scatterlist *dst, 7676cb9521SKevin Coffman struct scatterlist *src, 7776cb9521SKevin Coffman unsigned int offset, 7876cb9521SKevin Coffman unsigned int nbytes) 7976cb9521SKevin Coffman { 8076cb9521SKevin Coffman int bsize = crypto_blkcipher_blocksize(desc->tfm); 8176cb9521SKevin Coffman u8 tmp[bsize], tmp2[bsize]; 8276cb9521SKevin Coffman struct blkcipher_desc lcldesc; 8376cb9521SKevin Coffman struct scatterlist sgsrc[1], sgdst[1]; 8476cb9521SKevin Coffman int lastn = nbytes - bsize; 8576cb9521SKevin Coffman u8 iv[bsize]; 8676cb9521SKevin Coffman u8 s[bsize * 2], d[bsize * 2]; 8776cb9521SKevin Coffman int err; 8876cb9521SKevin Coffman 8976cb9521SKevin Coffman if (lastn < 0) 9076cb9521SKevin Coffman return -EINVAL; 9176cb9521SKevin Coffman 92c4913c7bSAlexey Dobriyan sg_init_table(sgsrc, 1); 93c4913c7bSAlexey Dobriyan sg_init_table(sgdst, 1); 94c4913c7bSAlexey Dobriyan 9576cb9521SKevin Coffman memset(s, 0, sizeof(s)); 9676cb9521SKevin Coffman scatterwalk_map_and_copy(s, src, offset, nbytes, 0); 9776cb9521SKevin Coffman 9876cb9521SKevin Coffman memcpy(iv, desc->info, bsize); 9976cb9521SKevin Coffman 10076cb9521SKevin Coffman lcldesc.tfm = ctx->child; 10176cb9521SKevin Coffman lcldesc.info = iv; 10276cb9521SKevin Coffman lcldesc.flags = desc->flags; 10376cb9521SKevin Coffman 10476cb9521SKevin Coffman sg_set_buf(&sgsrc[0], s, bsize); 10576cb9521SKevin Coffman sg_set_buf(&sgdst[0], tmp, bsize); 10676cb9521SKevin Coffman err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize); 10776cb9521SKevin Coffman 10876cb9521SKevin Coffman memcpy(d + bsize, tmp, lastn); 10976cb9521SKevin Coffman 11076cb9521SKevin Coffman lcldesc.info = tmp; 11176cb9521SKevin Coffman 11276cb9521SKevin Coffman sg_set_buf(&sgsrc[0], s + bsize, bsize); 11376cb9521SKevin Coffman sg_set_buf(&sgdst[0], tmp2, bsize); 11476cb9521SKevin Coffman err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize); 11576cb9521SKevin Coffman 11676cb9521SKevin Coffman memcpy(d, tmp2, bsize); 11776cb9521SKevin Coffman 11876cb9521SKevin Coffman scatterwalk_map_and_copy(d, dst, offset, nbytes, 1); 11976cb9521SKevin Coffman 12076cb9521SKevin Coffman memcpy(desc->info, tmp2, bsize); 12176cb9521SKevin Coffman 12276cb9521SKevin Coffman return err; 12376cb9521SKevin Coffman } 12476cb9521SKevin Coffman 12576cb9521SKevin Coffman static int crypto_cts_encrypt(struct blkcipher_desc *desc, 12676cb9521SKevin Coffman struct scatterlist *dst, struct scatterlist *src, 12776cb9521SKevin Coffman unsigned int nbytes) 12876cb9521SKevin Coffman { 12976cb9521SKevin Coffman struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 13076cb9521SKevin Coffman int bsize = crypto_blkcipher_blocksize(desc->tfm); 13176cb9521SKevin Coffman int tot_blocks = (nbytes + bsize - 1) / bsize; 13276cb9521SKevin Coffman int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0; 13376cb9521SKevin Coffman struct blkcipher_desc lcldesc; 13476cb9521SKevin Coffman int err; 13576cb9521SKevin Coffman 13676cb9521SKevin Coffman lcldesc.tfm = ctx->child; 13776cb9521SKevin Coffman lcldesc.info = desc->info; 13876cb9521SKevin Coffman lcldesc.flags = desc->flags; 13976cb9521SKevin Coffman 14076cb9521SKevin Coffman if (tot_blocks == 1) { 14176cb9521SKevin Coffman err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, bsize); 14276cb9521SKevin Coffman } else if (nbytes <= bsize * 2) { 14376cb9521SKevin Coffman err = cts_cbc_encrypt(ctx, desc, dst, src, 0, nbytes); 14476cb9521SKevin Coffman } else { 14576cb9521SKevin Coffman /* do normal function for tot_blocks - 2 */ 14676cb9521SKevin Coffman err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, 14776cb9521SKevin Coffman cbc_blocks * bsize); 14876cb9521SKevin Coffman if (err == 0) { 14976cb9521SKevin Coffman /* do cts for final two blocks */ 15076cb9521SKevin Coffman err = cts_cbc_encrypt(ctx, desc, dst, src, 15176cb9521SKevin Coffman cbc_blocks * bsize, 15276cb9521SKevin Coffman nbytes - (cbc_blocks * bsize)); 15376cb9521SKevin Coffman } 15476cb9521SKevin Coffman } 15576cb9521SKevin Coffman 15676cb9521SKevin Coffman return err; 15776cb9521SKevin Coffman } 15876cb9521SKevin Coffman 15976cb9521SKevin Coffman static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx, 16076cb9521SKevin Coffman struct blkcipher_desc *desc, 16176cb9521SKevin Coffman struct scatterlist *dst, 16276cb9521SKevin Coffman struct scatterlist *src, 16376cb9521SKevin Coffman unsigned int offset, 16476cb9521SKevin Coffman unsigned int nbytes) 16576cb9521SKevin Coffman { 16676cb9521SKevin Coffman int bsize = crypto_blkcipher_blocksize(desc->tfm); 16776cb9521SKevin Coffman u8 tmp[bsize]; 16876cb9521SKevin Coffman struct blkcipher_desc lcldesc; 16976cb9521SKevin Coffman struct scatterlist sgsrc[1], sgdst[1]; 17076cb9521SKevin Coffman int lastn = nbytes - bsize; 17176cb9521SKevin Coffman u8 iv[bsize]; 17276cb9521SKevin Coffman u8 s[bsize * 2], d[bsize * 2]; 17376cb9521SKevin Coffman int err; 17476cb9521SKevin Coffman 17576cb9521SKevin Coffman if (lastn < 0) 17676cb9521SKevin Coffman return -EINVAL; 17776cb9521SKevin Coffman 178c4913c7bSAlexey Dobriyan sg_init_table(sgsrc, 1); 179c4913c7bSAlexey Dobriyan sg_init_table(sgdst, 1); 180c4913c7bSAlexey Dobriyan 18176cb9521SKevin Coffman scatterwalk_map_and_copy(s, src, offset, nbytes, 0); 18276cb9521SKevin Coffman 18376cb9521SKevin Coffman lcldesc.tfm = ctx->child; 18476cb9521SKevin Coffman lcldesc.info = iv; 18576cb9521SKevin Coffman lcldesc.flags = desc->flags; 18676cb9521SKevin Coffman 18776cb9521SKevin Coffman /* 1. Decrypt Cn-1 (s) to create Dn (tmp)*/ 18876cb9521SKevin Coffman memset(iv, 0, sizeof(iv)); 18976cb9521SKevin Coffman sg_set_buf(&sgsrc[0], s, bsize); 19076cb9521SKevin Coffman sg_set_buf(&sgdst[0], tmp, bsize); 19176cb9521SKevin Coffman err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize); 19276cb9521SKevin Coffman if (err) 19376cb9521SKevin Coffman return err; 19476cb9521SKevin Coffman /* 2. Pad Cn with zeros at the end to create C of length BB */ 19576cb9521SKevin Coffman memset(iv, 0, sizeof(iv)); 19676cb9521SKevin Coffman memcpy(iv, s + bsize, lastn); 19776cb9521SKevin Coffman /* 3. Exclusive-or Dn (tmp) with C (iv) to create Xn (tmp) */ 19876cb9521SKevin Coffman crypto_xor(tmp, iv, bsize); 19976cb9521SKevin Coffman /* 4. Select the first Ln bytes of Xn (tmp) to create Pn */ 20076cb9521SKevin Coffman memcpy(d + bsize, tmp, lastn); 20176cb9521SKevin Coffman 20276cb9521SKevin Coffman /* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */ 20376cb9521SKevin Coffman memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn); 20476cb9521SKevin Coffman /* 6. Decrypt En to create Pn-1 */ 2057185ad26SDaniel Borkmann memzero_explicit(iv, sizeof(iv)); 2067185ad26SDaniel Borkmann 20776cb9521SKevin Coffman sg_set_buf(&sgsrc[0], s + bsize, bsize); 20876cb9521SKevin Coffman sg_set_buf(&sgdst[0], d, bsize); 20976cb9521SKevin Coffman err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize); 21076cb9521SKevin Coffman 21176cb9521SKevin Coffman /* XOR with previous block */ 21276cb9521SKevin Coffman crypto_xor(d, desc->info, bsize); 21376cb9521SKevin Coffman 21476cb9521SKevin Coffman scatterwalk_map_and_copy(d, dst, offset, nbytes, 1); 21576cb9521SKevin Coffman 21676cb9521SKevin Coffman memcpy(desc->info, s, bsize); 21776cb9521SKevin Coffman return err; 21876cb9521SKevin Coffman } 21976cb9521SKevin Coffman 22076cb9521SKevin Coffman static int crypto_cts_decrypt(struct blkcipher_desc *desc, 22176cb9521SKevin Coffman struct scatterlist *dst, struct scatterlist *src, 22276cb9521SKevin Coffman unsigned int nbytes) 22376cb9521SKevin Coffman { 22476cb9521SKevin Coffman struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 22576cb9521SKevin Coffman int bsize = crypto_blkcipher_blocksize(desc->tfm); 22676cb9521SKevin Coffman int tot_blocks = (nbytes + bsize - 1) / bsize; 22776cb9521SKevin Coffman int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0; 22876cb9521SKevin Coffman struct blkcipher_desc lcldesc; 22976cb9521SKevin Coffman int err; 23076cb9521SKevin Coffman 23176cb9521SKevin Coffman lcldesc.tfm = ctx->child; 23276cb9521SKevin Coffman lcldesc.info = desc->info; 23376cb9521SKevin Coffman lcldesc.flags = desc->flags; 23476cb9521SKevin Coffman 23576cb9521SKevin Coffman if (tot_blocks == 1) { 23676cb9521SKevin Coffman err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, bsize); 23776cb9521SKevin Coffman } else if (nbytes <= bsize * 2) { 23876cb9521SKevin Coffman err = cts_cbc_decrypt(ctx, desc, dst, src, 0, nbytes); 23976cb9521SKevin Coffman } else { 24076cb9521SKevin Coffman /* do normal function for tot_blocks - 2 */ 24176cb9521SKevin Coffman err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, 24276cb9521SKevin Coffman cbc_blocks * bsize); 24376cb9521SKevin Coffman if (err == 0) { 24476cb9521SKevin Coffman /* do cts for final two blocks */ 24576cb9521SKevin Coffman err = cts_cbc_decrypt(ctx, desc, dst, src, 24676cb9521SKevin Coffman cbc_blocks * bsize, 24776cb9521SKevin Coffman nbytes - (cbc_blocks * bsize)); 24876cb9521SKevin Coffman } 24976cb9521SKevin Coffman } 25076cb9521SKevin Coffman return err; 25176cb9521SKevin Coffman } 25276cb9521SKevin Coffman 25376cb9521SKevin Coffman static int crypto_cts_init_tfm(struct crypto_tfm *tfm) 25476cb9521SKevin Coffman { 25576cb9521SKevin Coffman struct crypto_instance *inst = (void *)tfm->__crt_alg; 25676cb9521SKevin Coffman struct crypto_spawn *spawn = crypto_instance_ctx(inst); 25776cb9521SKevin Coffman struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm); 25876cb9521SKevin Coffman struct crypto_blkcipher *cipher; 25976cb9521SKevin Coffman 26076cb9521SKevin Coffman cipher = crypto_spawn_blkcipher(spawn); 26176cb9521SKevin Coffman if (IS_ERR(cipher)) 26276cb9521SKevin Coffman return PTR_ERR(cipher); 26376cb9521SKevin Coffman 26476cb9521SKevin Coffman ctx->child = cipher; 26576cb9521SKevin Coffman return 0; 26676cb9521SKevin Coffman } 26776cb9521SKevin Coffman 26876cb9521SKevin Coffman static void crypto_cts_exit_tfm(struct crypto_tfm *tfm) 26976cb9521SKevin Coffman { 27076cb9521SKevin Coffman struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm); 27176cb9521SKevin Coffman crypto_free_blkcipher(ctx->child); 27276cb9521SKevin Coffman } 27376cb9521SKevin Coffman 27476cb9521SKevin Coffman static struct crypto_instance *crypto_cts_alloc(struct rtattr **tb) 27576cb9521SKevin Coffman { 27676cb9521SKevin Coffman struct crypto_instance *inst; 27776cb9521SKevin Coffman struct crypto_alg *alg; 27876cb9521SKevin Coffman int err; 27976cb9521SKevin Coffman 28076cb9521SKevin Coffman err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); 28176cb9521SKevin Coffman if (err) 28276cb9521SKevin Coffman return ERR_PTR(err); 28376cb9521SKevin Coffman 28476cb9521SKevin Coffman alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER, 28576cb9521SKevin Coffman CRYPTO_ALG_TYPE_MASK); 28676cb9521SKevin Coffman if (IS_ERR(alg)) 2873e8afe35SJulia Lawall return ERR_CAST(alg); 28876cb9521SKevin Coffman 28976cb9521SKevin Coffman inst = ERR_PTR(-EINVAL); 29076cb9521SKevin Coffman if (!is_power_of_2(alg->cra_blocksize)) 29176cb9521SKevin Coffman goto out_put_alg; 29276cb9521SKevin Coffman 29376cb9521SKevin Coffman inst = crypto_alloc_instance("cts", alg); 29476cb9521SKevin Coffman if (IS_ERR(inst)) 29576cb9521SKevin Coffman goto out_put_alg; 29676cb9521SKevin Coffman 29776cb9521SKevin Coffman inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; 29876cb9521SKevin Coffman inst->alg.cra_priority = alg->cra_priority; 29976cb9521SKevin Coffman inst->alg.cra_blocksize = alg->cra_blocksize; 30076cb9521SKevin Coffman inst->alg.cra_alignmask = alg->cra_alignmask; 30176cb9521SKevin Coffman inst->alg.cra_type = &crypto_blkcipher_type; 30276cb9521SKevin Coffman 30376cb9521SKevin Coffman /* We access the data as u32s when xoring. */ 30476cb9521SKevin Coffman inst->alg.cra_alignmask |= __alignof__(u32) - 1; 30576cb9521SKevin Coffman 30676cb9521SKevin Coffman inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize; 30776cb9521SKevin Coffman inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize; 30876cb9521SKevin Coffman inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize; 30976cb9521SKevin Coffman 31076cb9521SKevin Coffman inst->alg.cra_blkcipher.geniv = "seqiv"; 31176cb9521SKevin Coffman 31276cb9521SKevin Coffman inst->alg.cra_ctxsize = sizeof(struct crypto_cts_ctx); 31376cb9521SKevin Coffman 31476cb9521SKevin Coffman inst->alg.cra_init = crypto_cts_init_tfm; 31576cb9521SKevin Coffman inst->alg.cra_exit = crypto_cts_exit_tfm; 31676cb9521SKevin Coffman 31776cb9521SKevin Coffman inst->alg.cra_blkcipher.setkey = crypto_cts_setkey; 31876cb9521SKevin Coffman inst->alg.cra_blkcipher.encrypt = crypto_cts_encrypt; 31976cb9521SKevin Coffman inst->alg.cra_blkcipher.decrypt = crypto_cts_decrypt; 32076cb9521SKevin Coffman 32176cb9521SKevin Coffman out_put_alg: 32276cb9521SKevin Coffman crypto_mod_put(alg); 32376cb9521SKevin Coffman return inst; 32476cb9521SKevin Coffman } 32576cb9521SKevin Coffman 32676cb9521SKevin Coffman static void crypto_cts_free(struct crypto_instance *inst) 32776cb9521SKevin Coffman { 32876cb9521SKevin Coffman crypto_drop_spawn(crypto_instance_ctx(inst)); 32976cb9521SKevin Coffman kfree(inst); 33076cb9521SKevin Coffman } 33176cb9521SKevin Coffman 33276cb9521SKevin Coffman static struct crypto_template crypto_cts_tmpl = { 33376cb9521SKevin Coffman .name = "cts", 33476cb9521SKevin Coffman .alloc = crypto_cts_alloc, 33576cb9521SKevin Coffman .free = crypto_cts_free, 33676cb9521SKevin Coffman .module = THIS_MODULE, 33776cb9521SKevin Coffman }; 33876cb9521SKevin Coffman 33976cb9521SKevin Coffman static int __init crypto_cts_module_init(void) 34076cb9521SKevin Coffman { 34176cb9521SKevin Coffman return crypto_register_template(&crypto_cts_tmpl); 34276cb9521SKevin Coffman } 34376cb9521SKevin Coffman 34476cb9521SKevin Coffman static void __exit crypto_cts_module_exit(void) 34576cb9521SKevin Coffman { 34676cb9521SKevin Coffman crypto_unregister_template(&crypto_cts_tmpl); 34776cb9521SKevin Coffman } 34876cb9521SKevin Coffman 34976cb9521SKevin Coffman module_init(crypto_cts_module_init); 35076cb9521SKevin Coffman module_exit(crypto_cts_module_exit); 35176cb9521SKevin Coffman 35276cb9521SKevin Coffman MODULE_LICENSE("Dual BSD/GPL"); 35376cb9521SKevin Coffman MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC"); 354