162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* LRW: as defined by Cyril Guyot in 362306a36Sopenharmony_ci * http://grouper.ieee.org/groups/1619/email/pdf00017.pdf 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Based on ecb.c 862306a36Sopenharmony_ci * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci/* This implementation is checked against the test vectors in the above 1162306a36Sopenharmony_ci * document and by a test vector provided by Ken Buchanan at 1262306a36Sopenharmony_ci * https://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The test vectors are included in the testing module tcrypt.[ch] */ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 1762306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 1862306a36Sopenharmony_ci#include <linux/err.h> 1962306a36Sopenharmony_ci#include <linux/init.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/scatterlist.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <crypto/b128ops.h> 2662306a36Sopenharmony_ci#include <crypto/gf128mul.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define LRW_BLOCK_SIZE 16 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct lrw_tfm_ctx { 3162306a36Sopenharmony_ci struct crypto_skcipher *child; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci /* 3462306a36Sopenharmony_ci * optimizes multiplying a random (non incrementing, as at the 3562306a36Sopenharmony_ci * start of a new sector) value with key2, we could also have 3662306a36Sopenharmony_ci * used 4k optimization tables or no optimization at all. In the 3762306a36Sopenharmony_ci * latter case we would have to store key2 here 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci struct gf128mul_64k *table; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* 4262306a36Sopenharmony_ci * stores: 4362306a36Sopenharmony_ci * key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 }, 4462306a36Sopenharmony_ci * key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 } 4562306a36Sopenharmony_ci * key2*{ 0,0,...1,1,1,1,1 }, etc 4662306a36Sopenharmony_ci * needed for optimized multiplication of incrementing values 4762306a36Sopenharmony_ci * with key2 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci be128 mulinc[128]; 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistruct lrw_request_ctx { 5362306a36Sopenharmony_ci be128 t; 5462306a36Sopenharmony_ci struct skcipher_request subreq; 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic inline void lrw_setbit128_bbe(void *b, int bit) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci __set_bit(bit ^ (0x80 - 6062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN 6162306a36Sopenharmony_ci BITS_PER_LONG 6262306a36Sopenharmony_ci#else 6362306a36Sopenharmony_ci BITS_PER_BYTE 6462306a36Sopenharmony_ci#endif 6562306a36Sopenharmony_ci ), b); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int lrw_setkey(struct crypto_skcipher *parent, const u8 *key, 6962306a36Sopenharmony_ci unsigned int keylen) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct lrw_tfm_ctx *ctx = crypto_skcipher_ctx(parent); 7262306a36Sopenharmony_ci struct crypto_skcipher *child = ctx->child; 7362306a36Sopenharmony_ci int err, bsize = LRW_BLOCK_SIZE; 7462306a36Sopenharmony_ci const u8 *tweak = key + keylen - bsize; 7562306a36Sopenharmony_ci be128 tmp = { 0 }; 7662306a36Sopenharmony_ci int i; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 7962306a36Sopenharmony_ci crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & 8062306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 8162306a36Sopenharmony_ci err = crypto_skcipher_setkey(child, key, keylen - bsize); 8262306a36Sopenharmony_ci if (err) 8362306a36Sopenharmony_ci return err; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (ctx->table) 8662306a36Sopenharmony_ci gf128mul_free_64k(ctx->table); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* initialize multiplication table for Key2 */ 8962306a36Sopenharmony_ci ctx->table = gf128mul_init_64k_bbe((be128 *)tweak); 9062306a36Sopenharmony_ci if (!ctx->table) 9162306a36Sopenharmony_ci return -ENOMEM; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* initialize optimization table */ 9462306a36Sopenharmony_ci for (i = 0; i < 128; i++) { 9562306a36Sopenharmony_ci lrw_setbit128_bbe(&tmp, i); 9662306a36Sopenharmony_ci ctx->mulinc[i] = tmp; 9762306a36Sopenharmony_ci gf128mul_64k_bbe(&ctx->mulinc[i], ctx->table); 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return 0; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* 10462306a36Sopenharmony_ci * Returns the number of trailing '1' bits in the words of the counter, which is 10562306a36Sopenharmony_ci * represented by 4 32-bit words, arranged from least to most significant. 10662306a36Sopenharmony_ci * At the same time, increments the counter by one. 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * For example: 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * u32 counter[4] = { 0xFFFFFFFF, 0x1, 0x0, 0x0 }; 11162306a36Sopenharmony_ci * int i = lrw_next_index(&counter); 11262306a36Sopenharmony_ci * // i == 33, counter == { 0x0, 0x2, 0x0, 0x0 } 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_cistatic int lrw_next_index(u32 *counter) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci int i, res = 0; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 11962306a36Sopenharmony_ci if (counter[i] + 1 != 0) 12062306a36Sopenharmony_ci return res + ffz(counter[i]++); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci counter[i] = 0; 12362306a36Sopenharmony_ci res += 32; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * If we get here, then x == 128 and we are incrementing the counter 12862306a36Sopenharmony_ci * from all ones to all zeros. This means we must return index 127, i.e. 12962306a36Sopenharmony_ci * the one corresponding to key2*{ 1,...,1 }. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ci return 127; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* 13562306a36Sopenharmony_ci * We compute the tweak masks twice (both before and after the ECB encryption or 13662306a36Sopenharmony_ci * decryption) to avoid having to allocate a temporary buffer and/or make 13762306a36Sopenharmony_ci * mutliple calls to the 'ecb(..)' instance, which usually would be slower than 13862306a36Sopenharmony_ci * just doing the lrw_next_index() calls again. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_cistatic int lrw_xor_tweak(struct skcipher_request *req, bool second_pass) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci const int bs = LRW_BLOCK_SIZE; 14362306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 14462306a36Sopenharmony_ci const struct lrw_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 14562306a36Sopenharmony_ci struct lrw_request_ctx *rctx = skcipher_request_ctx(req); 14662306a36Sopenharmony_ci be128 t = rctx->t; 14762306a36Sopenharmony_ci struct skcipher_walk w; 14862306a36Sopenharmony_ci __be32 *iv; 14962306a36Sopenharmony_ci u32 counter[4]; 15062306a36Sopenharmony_ci int err; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if (second_pass) { 15362306a36Sopenharmony_ci req = &rctx->subreq; 15462306a36Sopenharmony_ci /* set to our TFM to enforce correct alignment: */ 15562306a36Sopenharmony_ci skcipher_request_set_tfm(req, tfm); 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci err = skcipher_walk_virt(&w, req, false); 15962306a36Sopenharmony_ci if (err) 16062306a36Sopenharmony_ci return err; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci iv = (__be32 *)w.iv; 16362306a36Sopenharmony_ci counter[0] = be32_to_cpu(iv[3]); 16462306a36Sopenharmony_ci counter[1] = be32_to_cpu(iv[2]); 16562306a36Sopenharmony_ci counter[2] = be32_to_cpu(iv[1]); 16662306a36Sopenharmony_ci counter[3] = be32_to_cpu(iv[0]); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci while (w.nbytes) { 16962306a36Sopenharmony_ci unsigned int avail = w.nbytes; 17062306a36Sopenharmony_ci be128 *wsrc; 17162306a36Sopenharmony_ci be128 *wdst; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci wsrc = w.src.virt.addr; 17462306a36Sopenharmony_ci wdst = w.dst.virt.addr; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci do { 17762306a36Sopenharmony_ci be128_xor(wdst++, &t, wsrc++); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* T <- I*Key2, using the optimization 18062306a36Sopenharmony_ci * discussed in the specification */ 18162306a36Sopenharmony_ci be128_xor(&t, &t, 18262306a36Sopenharmony_ci &ctx->mulinc[lrw_next_index(counter)]); 18362306a36Sopenharmony_ci } while ((avail -= bs) >= bs); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (second_pass && w.nbytes == w.total) { 18662306a36Sopenharmony_ci iv[0] = cpu_to_be32(counter[3]); 18762306a36Sopenharmony_ci iv[1] = cpu_to_be32(counter[2]); 18862306a36Sopenharmony_ci iv[2] = cpu_to_be32(counter[1]); 18962306a36Sopenharmony_ci iv[3] = cpu_to_be32(counter[0]); 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci err = skcipher_walk_done(&w, avail); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci return err; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic int lrw_xor_tweak_pre(struct skcipher_request *req) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci return lrw_xor_tweak(req, false); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic int lrw_xor_tweak_post(struct skcipher_request *req) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci return lrw_xor_tweak(req, true); 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic void lrw_crypt_done(void *data, int err) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct skcipher_request *req = data; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (!err) { 21362306a36Sopenharmony_ci struct lrw_request_ctx *rctx = skcipher_request_ctx(req); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 21662306a36Sopenharmony_ci err = lrw_xor_tweak_post(req); 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci skcipher_request_complete(req, err); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic void lrw_init_crypt(struct skcipher_request *req) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci const struct lrw_tfm_ctx *ctx = 22562306a36Sopenharmony_ci crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 22662306a36Sopenharmony_ci struct lrw_request_ctx *rctx = skcipher_request_ctx(req); 22762306a36Sopenharmony_ci struct skcipher_request *subreq = &rctx->subreq; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci skcipher_request_set_tfm(subreq, ctx->child); 23062306a36Sopenharmony_ci skcipher_request_set_callback(subreq, req->base.flags, lrw_crypt_done, 23162306a36Sopenharmony_ci req); 23262306a36Sopenharmony_ci /* pass req->iv as IV (will be used by xor_tweak, ECB will ignore it) */ 23362306a36Sopenharmony_ci skcipher_request_set_crypt(subreq, req->dst, req->dst, 23462306a36Sopenharmony_ci req->cryptlen, req->iv); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* calculate first value of T */ 23762306a36Sopenharmony_ci memcpy(&rctx->t, req->iv, sizeof(rctx->t)); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* T <- I*Key2 */ 24062306a36Sopenharmony_ci gf128mul_64k_bbe(&rctx->t, ctx->table); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic int lrw_encrypt(struct skcipher_request *req) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct lrw_request_ctx *rctx = skcipher_request_ctx(req); 24662306a36Sopenharmony_ci struct skcipher_request *subreq = &rctx->subreq; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci lrw_init_crypt(req); 24962306a36Sopenharmony_ci return lrw_xor_tweak_pre(req) ?: 25062306a36Sopenharmony_ci crypto_skcipher_encrypt(subreq) ?: 25162306a36Sopenharmony_ci lrw_xor_tweak_post(req); 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic int lrw_decrypt(struct skcipher_request *req) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct lrw_request_ctx *rctx = skcipher_request_ctx(req); 25762306a36Sopenharmony_ci struct skcipher_request *subreq = &rctx->subreq; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci lrw_init_crypt(req); 26062306a36Sopenharmony_ci return lrw_xor_tweak_pre(req) ?: 26162306a36Sopenharmony_ci crypto_skcipher_decrypt(subreq) ?: 26262306a36Sopenharmony_ci lrw_xor_tweak_post(req); 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic int lrw_init_tfm(struct crypto_skcipher *tfm) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct skcipher_instance *inst = skcipher_alg_instance(tfm); 26862306a36Sopenharmony_ci struct crypto_skcipher_spawn *spawn = skcipher_instance_ctx(inst); 26962306a36Sopenharmony_ci struct lrw_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 27062306a36Sopenharmony_ci struct crypto_skcipher *cipher; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci cipher = crypto_spawn_skcipher(spawn); 27362306a36Sopenharmony_ci if (IS_ERR(cipher)) 27462306a36Sopenharmony_ci return PTR_ERR(cipher); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci ctx->child = cipher; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(cipher) + 27962306a36Sopenharmony_ci sizeof(struct lrw_request_ctx)); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci return 0; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic void lrw_exit_tfm(struct crypto_skcipher *tfm) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct lrw_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (ctx->table) 28962306a36Sopenharmony_ci gf128mul_free_64k(ctx->table); 29062306a36Sopenharmony_ci crypto_free_skcipher(ctx->child); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic void lrw_free_instance(struct skcipher_instance *inst) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci crypto_drop_skcipher(skcipher_instance_ctx(inst)); 29662306a36Sopenharmony_ci kfree(inst); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic int lrw_create(struct crypto_template *tmpl, struct rtattr **tb) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct crypto_skcipher_spawn *spawn; 30262306a36Sopenharmony_ci struct skcipher_instance *inst; 30362306a36Sopenharmony_ci struct skcipher_alg *alg; 30462306a36Sopenharmony_ci const char *cipher_name; 30562306a36Sopenharmony_ci char ecb_name[CRYPTO_MAX_ALG_NAME]; 30662306a36Sopenharmony_ci u32 mask; 30762306a36Sopenharmony_ci int err; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask); 31062306a36Sopenharmony_ci if (err) 31162306a36Sopenharmony_ci return err; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci cipher_name = crypto_attr_alg_name(tb[1]); 31462306a36Sopenharmony_ci if (IS_ERR(cipher_name)) 31562306a36Sopenharmony_ci return PTR_ERR(cipher_name); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 31862306a36Sopenharmony_ci if (!inst) 31962306a36Sopenharmony_ci return -ENOMEM; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci spawn = skcipher_instance_ctx(inst); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci err = crypto_grab_skcipher(spawn, skcipher_crypto_instance(inst), 32462306a36Sopenharmony_ci cipher_name, 0, mask); 32562306a36Sopenharmony_ci if (err == -ENOENT) { 32662306a36Sopenharmony_ci err = -ENAMETOOLONG; 32762306a36Sopenharmony_ci if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)", 32862306a36Sopenharmony_ci cipher_name) >= CRYPTO_MAX_ALG_NAME) 32962306a36Sopenharmony_ci goto err_free_inst; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci err = crypto_grab_skcipher(spawn, 33262306a36Sopenharmony_ci skcipher_crypto_instance(inst), 33362306a36Sopenharmony_ci ecb_name, 0, mask); 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (err) 33762306a36Sopenharmony_ci goto err_free_inst; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci alg = crypto_skcipher_spawn_alg(spawn); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci err = -EINVAL; 34262306a36Sopenharmony_ci if (alg->base.cra_blocksize != LRW_BLOCK_SIZE) 34362306a36Sopenharmony_ci goto err_free_inst; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (crypto_skcipher_alg_ivsize(alg)) 34662306a36Sopenharmony_ci goto err_free_inst; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci err = crypto_inst_setname(skcipher_crypto_instance(inst), "lrw", 34962306a36Sopenharmony_ci &alg->base); 35062306a36Sopenharmony_ci if (err) 35162306a36Sopenharmony_ci goto err_free_inst; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci err = -EINVAL; 35462306a36Sopenharmony_ci cipher_name = alg->base.cra_name; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* Alas we screwed up the naming so we have to mangle the 35762306a36Sopenharmony_ci * cipher name. 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci if (!strncmp(cipher_name, "ecb(", 4)) { 36062306a36Sopenharmony_ci int len; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name)); 36362306a36Sopenharmony_ci if (len < 2) 36462306a36Sopenharmony_ci goto err_free_inst; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if (ecb_name[len - 1] != ')') 36762306a36Sopenharmony_ci goto err_free_inst; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ecb_name[len - 1] = 0; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 37262306a36Sopenharmony_ci "lrw(%s)", ecb_name) >= CRYPTO_MAX_ALG_NAME) { 37362306a36Sopenharmony_ci err = -ENAMETOOLONG; 37462306a36Sopenharmony_ci goto err_free_inst; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci } else 37762306a36Sopenharmony_ci goto err_free_inst; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci inst->alg.base.cra_priority = alg->base.cra_priority; 38062306a36Sopenharmony_ci inst->alg.base.cra_blocksize = LRW_BLOCK_SIZE; 38162306a36Sopenharmony_ci inst->alg.base.cra_alignmask = alg->base.cra_alignmask | 38262306a36Sopenharmony_ci (__alignof__(be128) - 1); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci inst->alg.ivsize = LRW_BLOCK_SIZE; 38562306a36Sopenharmony_ci inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) + 38662306a36Sopenharmony_ci LRW_BLOCK_SIZE; 38762306a36Sopenharmony_ci inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) + 38862306a36Sopenharmony_ci LRW_BLOCK_SIZE; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci inst->alg.base.cra_ctxsize = sizeof(struct lrw_tfm_ctx); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci inst->alg.init = lrw_init_tfm; 39362306a36Sopenharmony_ci inst->alg.exit = lrw_exit_tfm; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci inst->alg.setkey = lrw_setkey; 39662306a36Sopenharmony_ci inst->alg.encrypt = lrw_encrypt; 39762306a36Sopenharmony_ci inst->alg.decrypt = lrw_decrypt; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci inst->free = lrw_free_instance; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci err = skcipher_register_instance(tmpl, inst); 40262306a36Sopenharmony_ci if (err) { 40362306a36Sopenharmony_cierr_free_inst: 40462306a36Sopenharmony_ci lrw_free_instance(inst); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci return err; 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic struct crypto_template lrw_tmpl = { 41062306a36Sopenharmony_ci .name = "lrw", 41162306a36Sopenharmony_ci .create = lrw_create, 41262306a36Sopenharmony_ci .module = THIS_MODULE, 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic int __init lrw_module_init(void) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci return crypto_register_template(&lrw_tmpl); 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic void __exit lrw_module_exit(void) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci crypto_unregister_template(&lrw_tmpl); 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cisubsys_initcall(lrw_module_init); 42662306a36Sopenharmony_cimodule_exit(lrw_module_exit); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 42962306a36Sopenharmony_ciMODULE_DESCRIPTION("LRW block cipher mode"); 43062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("lrw"); 43162306a36Sopenharmony_ciMODULE_SOFTDEP("pre: ecb"); 432