Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.20-rc6 225 lines 5.4 kB view raw
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 22struct crypto_ofb_ctx { 23 struct crypto_cipher *child; 24 int cnt; 25}; 26 27 28static 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 44static 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 70static 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 */ 93static int crypto_ofb_decrypt(struct skcipher_request *req) 94{ 95 return crypto_ofb_encrypt(req); 96} 97 98static 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 113static 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 120static void crypto_ofb_free(struct skcipher_instance *inst) 121{ 122 crypto_drop_skcipher(skcipher_instance_ctx(inst)); 123 kfree(inst); 124} 125 126static 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 194out: 195 return err; 196 197err_drop_spawn: 198 crypto_drop_spawn(spawn); 199err_free_inst: 200 kfree(inst); 201 goto out; 202} 203 204static struct crypto_template crypto_ofb_tmpl = { 205 .name = "ofb", 206 .create = crypto_ofb_create, 207 .module = THIS_MODULE, 208}; 209 210static int __init crypto_ofb_module_init(void) 211{ 212 return crypto_register_template(&crypto_ofb_tmpl); 213} 214 215static void __exit crypto_ofb_module_exit(void) 216{ 217 crypto_unregister_template(&crypto_ofb_tmpl); 218} 219 220module_init(crypto_ofb_module_init); 221module_exit(crypto_ofb_module_exit); 222 223MODULE_LICENSE("GPL"); 224MODULE_DESCRIPTION("OFB block cipher algorithm"); 225MODULE_ALIAS_CRYPTO("ofb");