229 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ECB: Electronic CodeBook mode4 *5 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>6 */7 8#include <crypto/internal/cipher.h>9#include <crypto/internal/skcipher.h>10#include <linux/err.h>11#include <linux/init.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/slab.h>15 16static int crypto_ecb_crypt(struct crypto_cipher *cipher, const u8 *src,17 u8 *dst, unsigned nbytes, bool final,18 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))19{20 const unsigned int bsize = crypto_cipher_blocksize(cipher);21 22 while (nbytes >= bsize) {23 fn(crypto_cipher_tfm(cipher), dst, src);24 25 src += bsize;26 dst += bsize;27 28 nbytes -= bsize;29 }30 31 return nbytes && final ? -EINVAL : nbytes;32}33 34static int crypto_ecb_encrypt2(struct crypto_lskcipher *tfm, const u8 *src,35 u8 *dst, unsigned len, u8 *iv, u32 flags)36{37 struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);38 struct crypto_cipher *cipher = *ctx;39 40 return crypto_ecb_crypt(cipher, src, dst, len,41 flags & CRYPTO_LSKCIPHER_FLAG_FINAL,42 crypto_cipher_alg(cipher)->cia_encrypt);43}44 45static int crypto_ecb_decrypt2(struct crypto_lskcipher *tfm, const u8 *src,46 u8 *dst, unsigned len, u8 *iv, u32 flags)47{48 struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);49 struct crypto_cipher *cipher = *ctx;50 51 return crypto_ecb_crypt(cipher, src, dst, len,52 flags & CRYPTO_LSKCIPHER_FLAG_FINAL,53 crypto_cipher_alg(cipher)->cia_decrypt);54}55 56static int lskcipher_setkey_simple2(struct crypto_lskcipher *tfm,57 const u8 *key, unsigned int keylen)58{59 struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);60 struct crypto_cipher *cipher = *ctx;61 62 crypto_cipher_clear_flags(cipher, CRYPTO_TFM_REQ_MASK);63 crypto_cipher_set_flags(cipher, crypto_lskcipher_get_flags(tfm) &64 CRYPTO_TFM_REQ_MASK);65 return crypto_cipher_setkey(cipher, key, keylen);66}67 68static int lskcipher_init_tfm_simple2(struct crypto_lskcipher *tfm)69{70 struct lskcipher_instance *inst = lskcipher_alg_instance(tfm);71 struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);72 struct crypto_cipher_spawn *spawn;73 struct crypto_cipher *cipher;74 75 spawn = lskcipher_instance_ctx(inst);76 cipher = crypto_spawn_cipher(spawn);77 if (IS_ERR(cipher))78 return PTR_ERR(cipher);79 80 *ctx = cipher;81 return 0;82}83 84static void lskcipher_exit_tfm_simple2(struct crypto_lskcipher *tfm)85{86 struct crypto_cipher **ctx = crypto_lskcipher_ctx(tfm);87 88 crypto_free_cipher(*ctx);89}90 91static void lskcipher_free_instance_simple2(struct lskcipher_instance *inst)92{93 crypto_drop_cipher(lskcipher_instance_ctx(inst));94 kfree(inst);95}96 97static struct lskcipher_instance *lskcipher_alloc_instance_simple2(98 struct crypto_template *tmpl, struct rtattr **tb)99{100 struct crypto_cipher_spawn *spawn;101 struct lskcipher_instance *inst;102 struct crypto_alg *cipher_alg;103 u32 mask;104 int err;105 106 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_LSKCIPHER, &mask);107 if (err)108 return ERR_PTR(err);109 110 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);111 if (!inst)112 return ERR_PTR(-ENOMEM);113 spawn = lskcipher_instance_ctx(inst);114 115 err = crypto_grab_cipher(spawn, lskcipher_crypto_instance(inst),116 crypto_attr_alg_name(tb[1]), 0, mask);117 if (err)118 goto err_free_inst;119 cipher_alg = crypto_spawn_cipher_alg(spawn);120 121 err = crypto_inst_setname(lskcipher_crypto_instance(inst), tmpl->name,122 cipher_alg);123 if (err)124 goto err_free_inst;125 126 inst->free = lskcipher_free_instance_simple2;127 128 /* Default algorithm properties, can be overridden */129 inst->alg.co.base.cra_blocksize = cipher_alg->cra_blocksize;130 inst->alg.co.base.cra_alignmask = cipher_alg->cra_alignmask;131 inst->alg.co.base.cra_priority = cipher_alg->cra_priority;132 inst->alg.co.min_keysize = cipher_alg->cra_cipher.cia_min_keysize;133 inst->alg.co.max_keysize = cipher_alg->cra_cipher.cia_max_keysize;134 inst->alg.co.ivsize = cipher_alg->cra_blocksize;135 136 /* Use struct crypto_cipher * by default, can be overridden */137 inst->alg.co.base.cra_ctxsize = sizeof(struct crypto_cipher *);138 inst->alg.setkey = lskcipher_setkey_simple2;139 inst->alg.init = lskcipher_init_tfm_simple2;140 inst->alg.exit = lskcipher_exit_tfm_simple2;141 142 return inst;143 144err_free_inst:145 lskcipher_free_instance_simple2(inst);146 return ERR_PTR(err);147}148 149static int crypto_ecb_create2(struct crypto_template *tmpl, struct rtattr **tb)150{151 struct lskcipher_instance *inst;152 int err;153 154 inst = lskcipher_alloc_instance_simple2(tmpl, tb);155 if (IS_ERR(inst))156 return PTR_ERR(inst);157 158 /* ECB mode doesn't take an IV */159 inst->alg.co.ivsize = 0;160 161 inst->alg.encrypt = crypto_ecb_encrypt2;162 inst->alg.decrypt = crypto_ecb_decrypt2;163 164 err = lskcipher_register_instance(tmpl, inst);165 if (err)166 inst->free(inst);167 168 return err;169}170 171static int crypto_ecb_create(struct crypto_template *tmpl, struct rtattr **tb)172{173 struct crypto_lskcipher_spawn *spawn;174 struct lskcipher_alg *cipher_alg;175 struct lskcipher_instance *inst;176 int err;177 178 inst = lskcipher_alloc_instance_simple(tmpl, tb);179 if (IS_ERR(inst)) {180 err = crypto_ecb_create2(tmpl, tb);181 return err;182 }183 184 spawn = lskcipher_instance_ctx(inst);185 cipher_alg = crypto_lskcipher_spawn_alg(spawn);186 187 /* ECB mode doesn't take an IV */188 inst->alg.co.ivsize = 0;189 if (cipher_alg->co.ivsize)190 return -EINVAL;191 192 inst->alg.co.base.cra_ctxsize = cipher_alg->co.base.cra_ctxsize;193 inst->alg.setkey = cipher_alg->setkey;194 inst->alg.encrypt = cipher_alg->encrypt;195 inst->alg.decrypt = cipher_alg->decrypt;196 inst->alg.init = cipher_alg->init;197 inst->alg.exit = cipher_alg->exit;198 199 err = lskcipher_register_instance(tmpl, inst);200 if (err)201 inst->free(inst);202 203 return err;204}205 206static struct crypto_template crypto_ecb_tmpl = {207 .name = "ecb",208 .create = crypto_ecb_create,209 .module = THIS_MODULE,210};211 212static int __init crypto_ecb_module_init(void)213{214 return crypto_register_template(&crypto_ecb_tmpl);215}216 217static void __exit crypto_ecb_module_exit(void)218{219 crypto_unregister_template(&crypto_ecb_tmpl);220}221 222subsys_initcall(crypto_ecb_module_init);223module_exit(crypto_ecb_module_exit);224 225MODULE_LICENSE("GPL");226MODULE_DESCRIPTION("ECB block cipher mode of operation");227MODULE_ALIAS_CRYPTO("ecb");228MODULE_IMPORT_NS(CRYPTO_INTERNAL);229