- crypto_digest_init(tfm);
- crypto_digest_update(tfm, &tmp, 1);
-
- sg_set_buf(&tmp, out, crypto_tfm_alg_digestsize(tfm));
-
- crypto_digest_update(tfm, &tmp, 1);
- crypto_digest_final(tfm, out);
+static struct crypto_instance *hmac_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+ if (err)
+ return ERR_PTR(err);
+
+ alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
+ CRYPTO_ALG_TYPE_HASH_MASK);
+ if (IS_ERR(alg))
+ return ERR_PTR(PTR_ERR(alg));
+
+ inst = crypto_alloc_instance("hmac", alg);
+ if (IS_ERR(inst))
+ goto out_put_alg;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH;
+ 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_hash_type;
+
+ inst->alg.cra_hash.digestsize =
+ (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
+ alg->cra_digest.dia_digestsize;
+
+ inst->alg.cra_ctxsize = sizeof(struct hmac_ctx) +
+ ALIGN(inst->alg.cra_blocksize * 2 +
+ inst->alg.cra_hash.digestsize,
+ sizeof(void *));
+
+ inst->alg.cra_init = hmac_init_tfm;
+ inst->alg.cra_exit = hmac_exit_tfm;
+
+ inst->alg.cra_hash.init = hmac_init;
+ inst->alg.cra_hash.update = hmac_update;
+ inst->alg.cra_hash.final = hmac_final;
+ inst->alg.cra_hash.digest = hmac_digest;
+ inst->alg.cra_hash.setkey = hmac_setkey;
+
+out_put_alg:
+ crypto_mod_put(alg);
+ return inst;
+}
+
+static struct crypto_template hmac_tmpl = {
+ .name = "hmac",
+ .alloc = hmac_alloc,
+ .free = hmac_free,
+ .module = THIS_MODULE,
+};
+
+static int __init hmac_module_init(void)
+{
+ return crypto_register_template(&hmac_tmpl);