1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * OFB: Output FeedBack mode 5 * 6 * Copyright (C) 2018 ARM Limited or its affiliates. 7 * All rights reserved. 8 * 9 * Based loosely on public domain code gleaned from libtomcrypt 10 * (https://github.com/libtom/libtomcrypt). 11 */ 12 13 #include <crypto/algapi.h> 14 #include <crypto/internal/skcipher.h> 15 #include <linux/err.h> 16 #include <linux/init.h> 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/scatterlist.h> 20 #include <linux/slab.h> 21 22 struct crypto_ofb_ctx { 23 struct crypto_cipher *child; 24 int cnt; 25 }; 26 27 28 static int crypto_ofb_setkey(struct crypto_skcipher *parent, const u8 *key, 29 unsigned int keylen) 30 { 31 struct crypto_ofb_ctx *ctx = crypto_skcipher_ctx(parent); 32 struct crypto_cipher *child = ctx->child; 33 int err; 34 35 crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 36 crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) & 37 CRYPTO_TFM_REQ_MASK); 38 err = crypto_cipher_setkey(child, key, keylen); 39 crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) & 40 CRYPTO_TFM_RES_MASK); 41 return err; 42 } 43 44 static int crypto_ofb_encrypt_segment(struct crypto_ofb_ctx *ctx, 45 struct skcipher_walk *walk, 46 struct crypto_cipher *tfm) 47 { 48 int bsize = crypto_cipher_blocksize(tfm); 49 int nbytes = walk->nbytes; 50 51 u8 *src = walk->src.virt.addr; 52 u8 *dst = walk->dst.virt.addr; 53 u8 *iv = walk->iv; 54 55 do { 56 if (ctx->cnt == bsize) { 57 if (nbytes < bsize) 58 break; 59 crypto_cipher_encrypt_one(tfm, iv, iv); 60 ctx->cnt = 0; 61 } 62 *dst = *src ^ iv[ctx->cnt]; 63 src++; 64 dst++; 65 ctx->cnt++; 66 } while (--nbytes); 67 return nbytes; 68 } 69 70 static int crypto_ofb_encrypt(struct skcipher_request *req) 71 { 72 struct skcipher_walk walk; 73 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 74 unsigned int bsize; 75 struct crypto_ofb_ctx *ctx = crypto_skcipher_ctx(tfm); 76 struct crypto_cipher *child = ctx->child; 77 int ret = 0; 78 79 bsize = crypto_cipher_blocksize(child); 80 ctx->cnt = bsize; 81 82 ret = skcipher_walk_virt(&walk, req, false); 83 84 while (walk.nbytes) { 85 ret = crypto_ofb_encrypt_segment(ctx, &walk, child); 86 ret = skcipher_walk_done(&walk, ret); 87 } 88 89 return ret; 90 } 91 92 /* OFB encrypt and decrypt are identical */ 93 static int crypto_ofb_decrypt(struct skcipher_request *req) 94 { 95 return crypto_ofb_encrypt(req); 96 } 97 98 static int crypto_ofb_init_tfm(struct crypto_skcipher *tfm) 99 { 100 struct skcipher_instance *inst = skcipher_alg_instance(tfm); 101 struct crypto_spawn *spawn = skcipher_instance_ctx(inst); 102 struct crypto_ofb_ctx *ctx = crypto_skcipher_ctx(tfm); 103 struct crypto_cipher *cipher; 104 105 cipher = crypto_spawn_cipher(spawn); 106 if (IS_ERR(cipher)) 107 return PTR_ERR(cipher); 108 109 ctx->child = cipher; 110 return 0; 111 } 112 113 static void crypto_ofb_exit_tfm(struct crypto_skcipher *tfm) 114 { 115 struct crypto_ofb_ctx *ctx = crypto_skcipher_ctx(tfm); 116 117 crypto_free_cipher(ctx->child); 118 } 119 120 static void crypto_ofb_free(struct skcipher_instance *inst) 121 { 122 crypto_drop_skcipher(skcipher_instance_ctx(inst)); 123 kfree(inst); 124 } 125 126 static int crypto_ofb_create(struct crypto_template *tmpl, struct rtattr **tb) 127 { 128 struct skcipher_instance *inst; 129 struct crypto_attr_type *algt; 130 struct crypto_spawn *spawn; 131 struct crypto_alg *alg; 132 u32 mask; 133 int err; 134 135 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER); 136 if (err) 137 return err; 138 139 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 140 if (!inst) 141 return -ENOMEM; 142 143 algt = crypto_get_attr_type(tb); 144 err = PTR_ERR(algt); 145 if (IS_ERR(algt)) 146 goto err_free_inst; 147 148 mask = CRYPTO_ALG_TYPE_MASK | 149 crypto_requires_off(algt->type, algt->mask, 150 CRYPTO_ALG_NEED_FALLBACK); 151 152 alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, mask); 153 err = PTR_ERR(alg); 154 if (IS_ERR(alg)) 155 goto err_free_inst; 156 157 spawn = skcipher_instance_ctx(inst); 158 err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst), 159 CRYPTO_ALG_TYPE_MASK); 160 crypto_mod_put(alg); 161 if (err) 162 goto err_free_inst; 163 164 err = crypto_inst_setname(skcipher_crypto_instance(inst), "ofb", alg); 165 if (err) 166 goto err_drop_spawn; 167 168 inst->alg.base.cra_priority = alg->cra_priority; 169 inst->alg.base.cra_blocksize = alg->cra_blocksize; 170 inst->alg.base.cra_alignmask = alg->cra_alignmask; 171 172 /* We access the data as u32s when xoring. */ 173 inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; 174 175 inst->alg.ivsize = alg->cra_blocksize; 176 inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize; 177 inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize; 178 179 inst->alg.base.cra_ctxsize = sizeof(struct crypto_ofb_ctx); 180 181 inst->alg.init = crypto_ofb_init_tfm; 182 inst->alg.exit = crypto_ofb_exit_tfm; 183 184 inst->alg.setkey = crypto_ofb_setkey; 185 inst->alg.encrypt = crypto_ofb_encrypt; 186 inst->alg.decrypt = crypto_ofb_decrypt; 187 188 inst->free = crypto_ofb_free; 189 190 err = skcipher_register_instance(tmpl, inst); 191 if (err) 192 goto err_drop_spawn; 193 194 out: 195 return err; 196 197 err_drop_spawn: 198 crypto_drop_spawn(spawn); 199 err_free_inst: 200 kfree(inst); 201 goto out; 202 } 203 204 static struct crypto_template crypto_ofb_tmpl = { 205 .name = "ofb", 206 .create = crypto_ofb_create, 207 .module = THIS_MODULE, 208 }; 209 210 static int __init crypto_ofb_module_init(void) 211 { 212 return crypto_register_template(&crypto_ofb_tmpl); 213 } 214 215 static void __exit crypto_ofb_module_exit(void) 216 { 217 crypto_unregister_template(&crypto_ofb_tmpl); 218 } 219 220 module_init(crypto_ofb_module_init); 221 module_exit(crypto_ofb_module_exit); 222 223 MODULE_LICENSE("GPL"); 224 MODULE_DESCRIPTION("OFB block cipher algorithm"); 225 MODULE_ALIAS_CRYPTO("ofb"); 226