static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) { struct skcipher_instance *inst; struct crypto_attr_type *algt; struct crypto_spawn *spawn; struct crypto_alg *alg; u32 mask; int err; err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER); if (err) return err; inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) return -ENOMEM; algt = crypto_get_attr_type(tb); err = PTR_ERR(algt); if (IS_ERR(algt)) goto err_free_inst; mask = CRYPTO_ALG_TYPE_MASK | crypto_requires_off(algt->type, algt->mask, CRYPTO_ALG_NEED_FALLBACK); alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, mask); err = PTR_ERR(alg); if (IS_ERR(alg)) goto err_free_inst; spawn = skcipher_instance_ctx(inst); err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst), CRYPTO_ALG_TYPE_MASK); crypto_mod_put(alg); if (err) goto err_free_inst; err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg); if (err) goto err_drop_spawn; err = -EINVAL; if (!is_power_of_2(alg->cra_blocksize)) goto err_drop_spawn; inst->alg.base.cra_priority = alg->cra_priority; inst->alg.base.cra_blocksize = alg->cra_blocksize; inst->alg.base.cra_alignmask = alg->cra_alignmask; inst->alg.ivsize = alg->cra_blocksize; inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize; inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize; inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx); inst->alg.init = crypto_cbc_init_tfm; inst->alg.exit = crypto_cbc_exit_tfm; inst->alg.setkey = crypto_cbc_setkey; inst->alg.encrypt = crypto_cbc_encrypt; inst->alg.decrypt = crypto_cbc_decrypt; inst->free = crypto_cbc_free; err = skcipher_register_instance(tmpl, inst); if (err) goto err_drop_spawn; out: return err; err_drop_spawn: crypto_drop_spawn(spawn); err_free_inst: kfree(inst); goto out; }
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); 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); if (err) goto err_free_inst; alg = crypto_spawn_skcipher_alg(spawn); /* We only support 16-byte blocks. */ err = -EINVAL; if (crypto_skcipher_alg_ivsize(alg) != CTR_RFC3686_BLOCK_SIZE) goto err_drop_spawn; /* Not a stream cipher? */ if (alg->base.cra_blocksize != 1) goto err_drop_spawn; 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; 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; 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); inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) + CTR_RFC3686_NONCE_SIZE; inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) + CTR_RFC3686_NONCE_SIZE; inst->alg.setkey = crypto_rfc3686_setkey; inst->alg.encrypt = crypto_rfc3686_crypt; inst->alg.decrypt = crypto_rfc3686_crypt; inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx); inst->alg.init = crypto_rfc3686_init_tfm; inst->alg.exit = crypto_rfc3686_exit_tfm; 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); err_free_inst: kfree(inst); goto out; }