static void pkcs1pad_free(struct akcipher_instance *inst) { struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst); struct crypto_akcipher_spawn *spawn = &ctx->spawn; crypto_drop_akcipher(spawn); kfree(inst); }
static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; struct akcipher_instance *inst; struct pkcs1pad_inst_ctx *ctx; struct crypto_akcipher_spawn *spawn; struct akcipher_alg *rsa_alg; const char *rsa_alg_name; const char *hash_name; int err; algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return PTR_ERR(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AKCIPHER) & algt->mask) return -EINVAL; rsa_alg_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(rsa_alg_name)) return PTR_ERR(rsa_alg_name); hash_name = crypto_attr_alg_name(tb[2]); if (IS_ERR(hash_name)) hash_name = NULL; inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); if (!inst) return -ENOMEM; ctx = akcipher_instance_ctx(inst); spawn = &ctx->spawn; ctx->hash_name = hash_name ? kstrdup(hash_name, GFP_KERNEL) : NULL; crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst)); err = crypto_grab_akcipher(spawn, rsa_alg_name, 0, crypto_requires_sync(algt->type, algt->mask)); if (err) goto out_free_inst; rsa_alg = crypto_spawn_akcipher_alg(spawn); err = -ENAMETOOLONG; if (!hash_name) { if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME || snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", rsa_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) goto out_drop_alg; } else { if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)", rsa_alg->base.cra_name, hash_name) >= CRYPTO_MAX_ALG_NAME || snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)", rsa_alg->base.cra_driver_name, hash_name) >= CRYPTO_MAX_ALG_NAME) goto out_free_hash; } inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.base.cra_priority = rsa_alg->base.cra_priority; inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx); inst->alg.init = pkcs1pad_init_tfm; inst->alg.exit = pkcs1pad_exit_tfm; inst->alg.encrypt = pkcs1pad_encrypt; inst->alg.decrypt = pkcs1pad_decrypt; inst->alg.sign = pkcs1pad_sign; inst->alg.verify = pkcs1pad_verify; inst->alg.set_pub_key = pkcs1pad_set_pub_key; inst->alg.set_priv_key = pkcs1pad_set_priv_key; inst->alg.max_size = pkcs1pad_get_max_size; inst->alg.reqsize = sizeof(struct pkcs1pad_request) + rsa_alg->reqsize; inst->free = pkcs1pad_free; err = akcipher_register_instance(tmpl, inst); if (err) goto out_free_hash; return 0; out_free_hash: kfree(ctx->hash_name); out_drop_alg: crypto_drop_akcipher(spawn); out_free_inst: kfree(inst); return err; }