From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/crypto/ctr.c | 267 ++++++++++++++--------------------------------------- 1 files changed, 71 insertions(+), 196 deletions(-) diff --git a/kernel/crypto/ctr.c b/kernel/crypto/ctr.c index 435b75b..23c698b 100644 --- a/kernel/crypto/ctr.c +++ b/kernel/crypto/ctr.c @@ -1,29 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * CTR: Counter mode * * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * */ #include <crypto/algapi.h> #include <crypto/ctr.h> +#include <crypto/internal/cipher.h> #include <crypto/internal/skcipher.h> #include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/random.h> -#include <linux/scatterlist.h> #include <linux/slab.h> - -struct crypto_ctr_ctx { - struct crypto_cipher *child; -}; struct crypto_rfc3686_ctx { struct crypto_skcipher *child; @@ -35,24 +25,7 @@ struct skcipher_request subreq CRYPTO_MINALIGN_ATTR; }; -static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key, - unsigned int keylen) -{ - struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent); - struct crypto_cipher *child = ctx->child; - int err; - - crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & - CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(child, key, keylen); - crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; -} - -static void crypto_ctr_crypt_final(struct blkcipher_walk *walk, +static void crypto_ctr_crypt_final(struct skcipher_walk *walk, struct crypto_cipher *tfm) { unsigned int bsize = crypto_cipher_blocksize(tfm); @@ -70,7 +43,7 @@ crypto_inc(ctrblk, bsize); } -static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk, +static int crypto_ctr_crypt_segment(struct skcipher_walk *walk, struct crypto_cipher *tfm) { void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = @@ -96,7 +69,7 @@ return nbytes; } -static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk, +static int crypto_ctr_crypt_inplace(struct skcipher_walk *walk, struct crypto_cipher *tfm) { void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = @@ -123,146 +96,81 @@ return nbytes; } -static int crypto_ctr_crypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static int crypto_ctr_crypt(struct skcipher_request *req) { - struct blkcipher_walk walk; - struct crypto_blkcipher *tfm = desc->tfm; - struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm); - struct crypto_cipher *child = ctx->child; - unsigned int bsize = crypto_cipher_blocksize(child); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); + const unsigned int bsize = crypto_cipher_blocksize(cipher); + struct skcipher_walk walk; + unsigned int nbytes; int err; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, bsize); + err = skcipher_walk_virt(&walk, req, false); while (walk.nbytes >= bsize) { if (walk.src.virt.addr == walk.dst.virt.addr) - nbytes = crypto_ctr_crypt_inplace(&walk, child); + nbytes = crypto_ctr_crypt_inplace(&walk, cipher); else - nbytes = crypto_ctr_crypt_segment(&walk, child); + nbytes = crypto_ctr_crypt_segment(&walk, cipher); - err = blkcipher_walk_done(desc, &walk, nbytes); + err = skcipher_walk_done(&walk, nbytes); } if (walk.nbytes) { - crypto_ctr_crypt_final(&walk, child); - err = blkcipher_walk_done(desc, &walk, 0); + crypto_ctr_crypt_final(&walk, cipher); + err = skcipher_walk_done(&walk, 0); } return err; } -static int crypto_ctr_init_tfm(struct crypto_tfm *tfm) +static int crypto_ctr_create(struct crypto_template *tmpl, struct rtattr **tb) { - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm); - struct crypto_cipher *cipher; - - cipher = crypto_spawn_cipher(spawn); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - ctx->child = cipher; - - return 0; -} - -static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm) -{ - struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm); - - crypto_free_cipher(ctx->child); -} - -static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb) -{ - struct crypto_instance *inst; - struct crypto_attr_type *algt; + struct skcipher_instance *inst; struct crypto_alg *alg; - u32 mask; int err; - err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); - if (err) - return ERR_PTR(err); + inst = skcipher_alloc_instance_simple(tmpl, tb); + if (IS_ERR(inst)) + return PTR_ERR(inst); - algt = crypto_get_attr_type(tb); - if (IS_ERR(algt)) - return ERR_CAST(algt); - - mask = CRYPTO_ALG_TYPE_MASK | - crypto_requires_off(algt->type, algt->mask, - CRYPTO_ALG_NEED_FALLBACK); - - alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, mask); - if (IS_ERR(alg)) - return ERR_CAST(alg); + alg = skcipher_ialg_simple(inst); /* Block size must be >= 4 bytes. */ err = -EINVAL; if (alg->cra_blocksize < 4) - goto out_put_alg; + goto out_free_inst; /* If this is false we'd fail the alignment of crypto_inc. */ if (alg->cra_blocksize % 4) - goto out_put_alg; + goto out_free_inst; - inst = crypto_alloc_instance("ctr", alg); - if (IS_ERR(inst)) - goto out; + /* CTR mode is a stream cipher. */ + inst->alg.base.cra_blocksize = 1; - inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; - inst->alg.cra_priority = alg->cra_priority; - inst->alg.cra_blocksize = 1; - inst->alg.cra_alignmask = alg->cra_alignmask; - inst->alg.cra_type = &crypto_blkcipher_type; + /* + * To simplify the implementation, configure the skcipher walk to only + * give a partial block at the very end, never earlier. + */ + inst->alg.chunksize = alg->cra_blocksize; - inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize; - inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize; - inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize; + inst->alg.encrypt = crypto_ctr_crypt; + inst->alg.decrypt = crypto_ctr_crypt; - inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx); + err = skcipher_register_instance(tmpl, inst); + if (err) { +out_free_inst: + inst->free(inst); + } - inst->alg.cra_init = crypto_ctr_init_tfm; - inst->alg.cra_exit = crypto_ctr_exit_tfm; - - inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey; - inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt; - inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt; - - inst->alg.cra_blkcipher.geniv = "chainiv"; - -out: - crypto_mod_put(alg); - return inst; - -out_put_alg: - inst = ERR_PTR(err); - goto out; + return err; } - -static void crypto_ctr_free(struct crypto_instance *inst) -{ - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(inst); -} - -static struct crypto_template crypto_ctr_tmpl = { - .name = "ctr", - .alloc = crypto_ctr_alloc, - .free = crypto_ctr_free, - .module = THIS_MODULE, -}; static int crypto_rfc3686_setkey(struct crypto_skcipher *parent, const u8 *key, unsigned int keylen) { struct crypto_rfc3686_ctx *ctx = crypto_skcipher_ctx(parent); struct crypto_skcipher *child = ctx->child; - int err; /* the nonce is stored in bytes at end of key */ if (keylen < CTR_RFC3686_NONCE_SIZE) @@ -276,11 +184,7 @@ crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - - return err; + return crypto_skcipher_setkey(child, key, keylen); } static int crypto_rfc3686_crypt(struct skcipher_request *req) @@ -353,38 +257,24 @@ static int crypto_rfc3686_create(struct crypto_template *tmpl, struct rtattr **tb) { - struct crypto_attr_type *algt; struct skcipher_instance *inst; struct skcipher_alg *alg; struct crypto_skcipher_spawn *spawn; - const char *cipher_name; u32 mask; - int err; - algt = crypto_get_attr_type(tb); - if (IS_ERR(algt)) - return PTR_ERR(algt); - - if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask) - return -EINVAL; - - cipher_name = crypto_attr_alg_name(tb[1]); - if (IS_ERR(cipher_name)) - return PTR_ERR(cipher_name); + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask); + if (err) + return err; inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) return -ENOMEM; - mask = crypto_requires_sync(algt->type, algt->mask) | - crypto_requires_off(algt->type, algt->mask, - CRYPTO_ALG_NEED_FALLBACK); - spawn = skcipher_instance_ctx(inst); - crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(spawn, cipher_name, 0, mask); + err = crypto_grab_skcipher(spawn, skcipher_crypto_instance(inst), + crypto_attr_alg_name(tb[1]), 0, mask); if (err) goto err_free_inst; @@ -393,26 +283,24 @@ /* We only support 16-byte blocks. */ err = -EINVAL; if (crypto_skcipher_alg_ivsize(alg) != CTR_RFC3686_BLOCK_SIZE) - goto err_drop_spawn; + goto err_free_inst; /* Not a stream cipher? */ if (alg->base.cra_blocksize != 1) - goto err_drop_spawn; + goto err_free_inst; err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "rfc3686(%s)", alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_spawn; + goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "rfc3686(%s)", alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto err_drop_spawn; + goto err_free_inst; inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = alg->base.cra_alignmask; - - inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.ivsize = CTR_RFC3686_IV_SIZE; inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg); @@ -433,55 +321,42 @@ inst->free = crypto_rfc3686_free; err = skcipher_register_instance(tmpl, inst); - if (err) - goto err_drop_spawn; - -out: - return err; - -err_drop_spawn: - crypto_drop_skcipher(spawn); + if (err) { err_free_inst: - kfree(inst); - goto out; + crypto_rfc3686_free(inst); + } + return err; } -static struct crypto_template crypto_rfc3686_tmpl = { - .name = "rfc3686", - .create = crypto_rfc3686_create, - .module = THIS_MODULE, +static struct crypto_template crypto_ctr_tmpls[] = { + { + .name = "ctr", + .create = crypto_ctr_create, + .module = THIS_MODULE, + }, { + .name = "rfc3686", + .create = crypto_rfc3686_create, + .module = THIS_MODULE, + }, }; static int __init crypto_ctr_module_init(void) { - int err; - - err = crypto_register_template(&crypto_ctr_tmpl); - if (err) - goto out; - - err = crypto_register_template(&crypto_rfc3686_tmpl); - if (err) - goto out_drop_ctr; - -out: - return err; - -out_drop_ctr: - crypto_unregister_template(&crypto_ctr_tmpl); - goto out; + return crypto_register_templates(crypto_ctr_tmpls, + ARRAY_SIZE(crypto_ctr_tmpls)); } static void __exit crypto_ctr_module_exit(void) { - crypto_unregister_template(&crypto_rfc3686_tmpl); - crypto_unregister_template(&crypto_ctr_tmpl); + crypto_unregister_templates(crypto_ctr_tmpls, + ARRAY_SIZE(crypto_ctr_tmpls)); } -module_init(crypto_ctr_module_init); +subsys_initcall(crypto_ctr_module_init); module_exit(crypto_ctr_module_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("CTR Counter block mode"); +MODULE_DESCRIPTION("CTR block cipher mode of operation"); MODULE_ALIAS_CRYPTO("rfc3686"); MODULE_ALIAS_CRYPTO("ctr"); +MODULE_IMPORT_NS(CRYPTO_INTERNAL); -- Gitblit v1.6.2