static struct crypto_instance *crypto_rfc4309_alloc(struct rtattr **tb) { struct crypto_attr_type *algt; struct crypto_instance *inst; struct crypto_aead_spawn *spawn; struct crypto_alg *alg; const char *ccm_name; int err; algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); ccm_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(ccm_name)) return ERR_CAST(ccm_name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) return ERR_PTR(-ENOMEM); spawn = crypto_instance_ctx(inst); crypto_set_aead_spawn(spawn, inst); err = crypto_grab_aead(spawn, ccm_name, 0, crypto_requires_sync(algt->type, algt->mask)); if (err) goto out_free_inst; alg = crypto_aead_spawn_alg(spawn); err = -EINVAL; /* We only support 16-byte blocks. */ if (alg->cra_aead.ivsize != 16) goto out_drop_alg; /* Not a stream cipher? */ if (alg->cra_blocksize != 1) goto out_drop_alg; err = -ENAMETOOLONG; if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "rfc4309(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME || snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "rfc4309(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) goto out_drop_alg; inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD; inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC; inst->alg.cra_priority = alg->cra_priority; inst->alg.cra_blocksize = 1; inst->alg.cra_alignmask = alg->cra_alignmask; inst->alg.cra_type = &crypto_nivaead_type; inst->alg.cra_aead.ivsize = 8; inst->alg.cra_aead.maxauthsize = 16; inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx); inst->alg.cra_init = crypto_rfc4309_init_tfm; inst->alg.cra_exit = crypto_rfc4309_exit_tfm; inst->alg.cra_aead.setkey = crypto_rfc4309_setkey; inst->alg.cra_aead.setauthsize = crypto_rfc4309_setauthsize; inst->alg.cra_aead.encrypt = crypto_rfc4309_encrypt; inst->alg.cra_aead.decrypt = crypto_rfc4309_decrypt; inst->alg.cra_aead.geniv = "seqiv"; out: return inst; out_drop_alg: crypto_drop_aead(spawn); out_free_inst: kfree(inst); inst = ERR_PTR(err); goto out; }
static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb, u32 type, u32 mask) { struct pcrypt_instance_ctx *ctx; struct crypto_attr_type *algt; struct aead_instance *inst; struct aead_alg *alg; const char *name; int err; algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return PTR_ERR(algt); name = crypto_attr_alg_name(tb[1]); if (IS_ERR(name)) return PTR_ERR(name); inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); if (!inst) return -ENOMEM; ctx = aead_instance_ctx(inst); crypto_set_aead_spawn(&ctx->spawn, aead_crypto_instance(inst)); err = crypto_grab_aead(&ctx->spawn, name, 0, 0); if (err) goto out_free_inst; alg = crypto_spawn_aead_alg(&ctx->spawn); err = pcrypt_init_instance(aead_crypto_instance(inst), &alg->base); if (err) goto out_drop_aead; inst->alg.base.cra_flags = CRYPTO_ALG_ASYNC; inst->alg.ivsize = crypto_aead_alg_ivsize(alg); inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg); inst->alg.base.cra_ctxsize = sizeof(struct pcrypt_aead_ctx); inst->alg.init = pcrypt_aead_init_tfm; inst->alg.exit = pcrypt_aead_exit_tfm; inst->alg.setkey = pcrypt_aead_setkey; inst->alg.setauthsize = pcrypt_aead_setauthsize; inst->alg.encrypt = pcrypt_aead_encrypt; inst->alg.decrypt = pcrypt_aead_decrypt; inst->free = pcrypt_free; err = aead_register_instance(tmpl, inst); if (err) goto out_drop_aead; out: return err; out_drop_aead: crypto_drop_aead(&ctx->spawn); out_free_inst: kfree(inst); goto out; }
struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl, struct rtattr **tb, u32 type, u32 mask) { const char *name; struct crypto_aead_spawn *spawn; struct crypto_attr_type *algt; struct crypto_instance *inst; struct crypto_alg *alg; int err; algt = crypto_get_attr_type(tb); err = PTR_ERR(algt); if (IS_ERR(algt)) return ERR_PTR(err); if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) & algt->mask) return ERR_PTR(-EINVAL); name = crypto_attr_alg_name(tb[1]); err = PTR_ERR(name); if (IS_ERR(name)) return ERR_PTR(err); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) return ERR_PTR(-ENOMEM); spawn = crypto_instance_ctx(inst); /* Ignore async algorithms if necessary. */ mask |= crypto_requires_sync(algt->type, algt->mask); crypto_set_aead_spawn(spawn, inst); err = crypto_grab_nivaead(spawn, name, type, mask); if (err) goto err_free_inst; alg = crypto_aead_spawn_alg(spawn); err = -EINVAL; if (!alg->cra_aead.ivsize) goto err_drop_alg; /* * This is only true if we're constructing an algorithm with its * default IV generator. For the default generator we elide the * template name and double-check the IV generator. */ if (algt->mask & CRYPTO_ALG_GENIV) { if (strcmp(tmpl->name, alg->cra_aead.geniv)) goto err_drop_alg; memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); memcpy(inst->alg.cra_driver_name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME); } else { err = -ENAMETOOLONG; if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", tmpl->name, alg->cra_name) >= CRYPTO_MAX_ALG_NAME) goto err_drop_alg; if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", tmpl->name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) goto err_drop_alg; } inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV; inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC; inst->alg.cra_priority = alg->cra_priority; inst->alg.cra_blocksize = alg->cra_blocksize; inst->alg.cra_alignmask = alg->cra_alignmask; inst->alg.cra_type = &crypto_aead_type; inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize; inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize; inst->alg.cra_aead.geniv = alg->cra_aead.geniv; inst->alg.cra_aead.setkey = alg->cra_aead.setkey; inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize; inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt; inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt; out: return inst; err_drop_alg: crypto_drop_aead(spawn); err_free_inst: kfree(inst); inst = ERR_PTR(err); goto out; }
static int crypto_rfc4309_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; struct aead_instance *inst; struct crypto_aead_spawn *spawn; struct aead_alg *alg; const char *ccm_name; int err; algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return PTR_ERR(algt); if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_AEAD_NEW)) & algt->mask) return -EINVAL; ccm_name = crypto_attr_alg_name(tb[1]); if (IS_ERR(ccm_name)) return PTR_ERR(ccm_name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) return -ENOMEM; spawn = aead_instance_ctx(inst); crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); err = crypto_grab_aead(spawn, ccm_name, 0, crypto_requires_sync(algt->type, algt->mask)); if (err) goto out_free_inst; alg = crypto_spawn_aead_alg(spawn); err = -EINVAL; /* We only support 16-byte blocks. */ if (crypto_aead_alg_ivsize(alg) != 16) goto out_drop_alg; /* Not a stream cipher? */ if (alg->base.cra_blocksize != 1) goto out_drop_alg; err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "rfc4309(%s)", alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME || snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "rfc4309(%s)", alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) goto out_drop_alg; inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.base.cra_flags |= CRYPTO_ALG_AEAD_NEW; 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.ivsize = 8; inst->alg.maxauthsize = 16; inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx); inst->alg.init = crypto_rfc4309_init_tfm; inst->alg.exit = crypto_rfc4309_exit_tfm; inst->alg.setkey = crypto_rfc4309_setkey; inst->alg.setauthsize = crypto_rfc4309_setauthsize; inst->alg.encrypt = crypto_rfc4309_encrypt; inst->alg.decrypt = crypto_rfc4309_decrypt; inst->free = crypto_rfc4309_free; err = aead_register_instance(tmpl, inst); if (err) goto out_drop_alg; out: return err; out_drop_alg: crypto_drop_aead(spawn); out_free_inst: kfree(inst); goto out; }