0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <crypto/algapi.h>
0023 #include <crypto/internal/cipher.h>
0024 #include <crypto/internal/skcipher.h>
0025 #include <linux/err.h>
0026 #include <linux/init.h>
0027 #include <linux/kernel.h>
0028 #include <linux/module.h>
0029 #include <linux/string.h>
0030
0031 static unsigned int crypto_cfb_bsize(struct crypto_skcipher *tfm)
0032 {
0033 return crypto_cipher_blocksize(skcipher_cipher_simple(tfm));
0034 }
0035
0036 static void crypto_cfb_encrypt_one(struct crypto_skcipher *tfm,
0037 const u8 *src, u8 *dst)
0038 {
0039 crypto_cipher_encrypt_one(skcipher_cipher_simple(tfm), dst, src);
0040 }
0041
0042
0043 static void crypto_cfb_final(struct skcipher_walk *walk,
0044 struct crypto_skcipher *tfm)
0045 {
0046 const unsigned long alignmask = crypto_skcipher_alignmask(tfm);
0047 u8 tmp[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK];
0048 u8 *stream = PTR_ALIGN(tmp + 0, alignmask + 1);
0049 u8 *src = walk->src.virt.addr;
0050 u8 *dst = walk->dst.virt.addr;
0051 u8 *iv = walk->iv;
0052 unsigned int nbytes = walk->nbytes;
0053
0054 crypto_cfb_encrypt_one(tfm, iv, stream);
0055 crypto_xor_cpy(dst, stream, src, nbytes);
0056 }
0057
0058 static int crypto_cfb_encrypt_segment(struct skcipher_walk *walk,
0059 struct crypto_skcipher *tfm)
0060 {
0061 const unsigned int bsize = crypto_cfb_bsize(tfm);
0062 unsigned int nbytes = walk->nbytes;
0063 u8 *src = walk->src.virt.addr;
0064 u8 *dst = walk->dst.virt.addr;
0065 u8 *iv = walk->iv;
0066
0067 do {
0068 crypto_cfb_encrypt_one(tfm, iv, dst);
0069 crypto_xor(dst, src, bsize);
0070 iv = dst;
0071
0072 src += bsize;
0073 dst += bsize;
0074 } while ((nbytes -= bsize) >= bsize);
0075
0076 memcpy(walk->iv, iv, bsize);
0077
0078 return nbytes;
0079 }
0080
0081 static int crypto_cfb_encrypt_inplace(struct skcipher_walk *walk,
0082 struct crypto_skcipher *tfm)
0083 {
0084 const unsigned int bsize = crypto_cfb_bsize(tfm);
0085 unsigned int nbytes = walk->nbytes;
0086 u8 *src = walk->src.virt.addr;
0087 u8 *iv = walk->iv;
0088 u8 tmp[MAX_CIPHER_BLOCKSIZE];
0089
0090 do {
0091 crypto_cfb_encrypt_one(tfm, iv, tmp);
0092 crypto_xor(src, tmp, bsize);
0093 iv = src;
0094
0095 src += bsize;
0096 } while ((nbytes -= bsize) >= bsize);
0097
0098 memcpy(walk->iv, iv, bsize);
0099
0100 return nbytes;
0101 }
0102
0103 static int crypto_cfb_encrypt(struct skcipher_request *req)
0104 {
0105 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0106 struct skcipher_walk walk;
0107 unsigned int bsize = crypto_cfb_bsize(tfm);
0108 int err;
0109
0110 err = skcipher_walk_virt(&walk, req, false);
0111
0112 while (walk.nbytes >= bsize) {
0113 if (walk.src.virt.addr == walk.dst.virt.addr)
0114 err = crypto_cfb_encrypt_inplace(&walk, tfm);
0115 else
0116 err = crypto_cfb_encrypt_segment(&walk, tfm);
0117 err = skcipher_walk_done(&walk, err);
0118 }
0119
0120 if (walk.nbytes) {
0121 crypto_cfb_final(&walk, tfm);
0122 err = skcipher_walk_done(&walk, 0);
0123 }
0124
0125 return err;
0126 }
0127
0128 static int crypto_cfb_decrypt_segment(struct skcipher_walk *walk,
0129 struct crypto_skcipher *tfm)
0130 {
0131 const unsigned int bsize = crypto_cfb_bsize(tfm);
0132 unsigned int nbytes = walk->nbytes;
0133 u8 *src = walk->src.virt.addr;
0134 u8 *dst = walk->dst.virt.addr;
0135 u8 *iv = walk->iv;
0136
0137 do {
0138 crypto_cfb_encrypt_one(tfm, iv, dst);
0139 crypto_xor(dst, src, bsize);
0140 iv = src;
0141
0142 src += bsize;
0143 dst += bsize;
0144 } while ((nbytes -= bsize) >= bsize);
0145
0146 memcpy(walk->iv, iv, bsize);
0147
0148 return nbytes;
0149 }
0150
0151 static int crypto_cfb_decrypt_inplace(struct skcipher_walk *walk,
0152 struct crypto_skcipher *tfm)
0153 {
0154 const unsigned int bsize = crypto_cfb_bsize(tfm);
0155 unsigned int nbytes = walk->nbytes;
0156 u8 *src = walk->src.virt.addr;
0157 u8 * const iv = walk->iv;
0158 u8 tmp[MAX_CIPHER_BLOCKSIZE];
0159
0160 do {
0161 crypto_cfb_encrypt_one(tfm, iv, tmp);
0162 memcpy(iv, src, bsize);
0163 crypto_xor(src, tmp, bsize);
0164 src += bsize;
0165 } while ((nbytes -= bsize) >= bsize);
0166
0167 return nbytes;
0168 }
0169
0170 static int crypto_cfb_decrypt_blocks(struct skcipher_walk *walk,
0171 struct crypto_skcipher *tfm)
0172 {
0173 if (walk->src.virt.addr == walk->dst.virt.addr)
0174 return crypto_cfb_decrypt_inplace(walk, tfm);
0175 else
0176 return crypto_cfb_decrypt_segment(walk, tfm);
0177 }
0178
0179 static int crypto_cfb_decrypt(struct skcipher_request *req)
0180 {
0181 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0182 struct skcipher_walk walk;
0183 const unsigned int bsize = crypto_cfb_bsize(tfm);
0184 int err;
0185
0186 err = skcipher_walk_virt(&walk, req, false);
0187
0188 while (walk.nbytes >= bsize) {
0189 err = crypto_cfb_decrypt_blocks(&walk, tfm);
0190 err = skcipher_walk_done(&walk, err);
0191 }
0192
0193 if (walk.nbytes) {
0194 crypto_cfb_final(&walk, tfm);
0195 err = skcipher_walk_done(&walk, 0);
0196 }
0197
0198 return err;
0199 }
0200
0201 static int crypto_cfb_create(struct crypto_template *tmpl, struct rtattr **tb)
0202 {
0203 struct skcipher_instance *inst;
0204 struct crypto_alg *alg;
0205 int err;
0206
0207 inst = skcipher_alloc_instance_simple(tmpl, tb);
0208 if (IS_ERR(inst))
0209 return PTR_ERR(inst);
0210
0211 alg = skcipher_ialg_simple(inst);
0212
0213
0214 inst->alg.base.cra_blocksize = 1;
0215
0216
0217
0218
0219
0220 inst->alg.chunksize = alg->cra_blocksize;
0221
0222 inst->alg.encrypt = crypto_cfb_encrypt;
0223 inst->alg.decrypt = crypto_cfb_decrypt;
0224
0225 err = skcipher_register_instance(tmpl, inst);
0226 if (err)
0227 inst->free(inst);
0228
0229 return err;
0230 }
0231
0232 static struct crypto_template crypto_cfb_tmpl = {
0233 .name = "cfb",
0234 .create = crypto_cfb_create,
0235 .module = THIS_MODULE,
0236 };
0237
0238 static int __init crypto_cfb_module_init(void)
0239 {
0240 return crypto_register_template(&crypto_cfb_tmpl);
0241 }
0242
0243 static void __exit crypto_cfb_module_exit(void)
0244 {
0245 crypto_unregister_template(&crypto_cfb_tmpl);
0246 }
0247
0248 subsys_initcall(crypto_cfb_module_init);
0249 module_exit(crypto_cfb_module_exit);
0250
0251 MODULE_LICENSE("GPL");
0252 MODULE_DESCRIPTION("CFB block cipher mode of operation");
0253 MODULE_ALIAS_CRYPTO("cfb");
0254 MODULE_IMPORT_NS(CRYPTO_INTERNAL);