1*004a403cSLoc Ho /* 2*004a403cSLoc Ho * Asynchronous Cryptographic Hash operations. 3*004a403cSLoc Ho * 4*004a403cSLoc Ho * This is the asynchronous version of hash.c with notification of 5*004a403cSLoc Ho * completion via a callback. 6*004a403cSLoc Ho * 7*004a403cSLoc Ho * Copyright (c) 2008 Loc Ho <lho@amcc.com> 8*004a403cSLoc Ho * 9*004a403cSLoc Ho * This program is free software; you can redistribute it and/or modify it 10*004a403cSLoc Ho * under the terms of the GNU General Public License as published by the Free 11*004a403cSLoc Ho * Software Foundation; either version 2 of the License, or (at your option) 12*004a403cSLoc Ho * any later version. 13*004a403cSLoc Ho * 14*004a403cSLoc Ho */ 15*004a403cSLoc Ho 16*004a403cSLoc Ho #include <crypto/algapi.h> 17*004a403cSLoc Ho #include <linux/err.h> 18*004a403cSLoc Ho #include <linux/kernel.h> 19*004a403cSLoc Ho #include <linux/module.h> 20*004a403cSLoc Ho #include <linux/sched.h> 21*004a403cSLoc Ho #include <linux/slab.h> 22*004a403cSLoc Ho #include <linux/seq_file.h> 23*004a403cSLoc Ho 24*004a403cSLoc Ho #include "internal.h" 25*004a403cSLoc Ho 26*004a403cSLoc Ho static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key, 27*004a403cSLoc Ho unsigned int keylen) 28*004a403cSLoc Ho { 29*004a403cSLoc Ho struct ahash_alg *ahash = crypto_ahash_alg(tfm); 30*004a403cSLoc Ho unsigned long alignmask = crypto_ahash_alignmask(tfm); 31*004a403cSLoc Ho int ret; 32*004a403cSLoc Ho u8 *buffer, *alignbuffer; 33*004a403cSLoc Ho unsigned long absize; 34*004a403cSLoc Ho 35*004a403cSLoc Ho absize = keylen + alignmask; 36*004a403cSLoc Ho buffer = kmalloc(absize, GFP_ATOMIC); 37*004a403cSLoc Ho if (!buffer) 38*004a403cSLoc Ho return -ENOMEM; 39*004a403cSLoc Ho 40*004a403cSLoc Ho alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 41*004a403cSLoc Ho memcpy(alignbuffer, key, keylen); 42*004a403cSLoc Ho ret = ahash->setkey(tfm, alignbuffer, keylen); 43*004a403cSLoc Ho memset(alignbuffer, 0, keylen); 44*004a403cSLoc Ho kfree(buffer); 45*004a403cSLoc Ho return ret; 46*004a403cSLoc Ho } 47*004a403cSLoc Ho 48*004a403cSLoc Ho static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 49*004a403cSLoc Ho unsigned int keylen) 50*004a403cSLoc Ho { 51*004a403cSLoc Ho struct ahash_alg *ahash = crypto_ahash_alg(tfm); 52*004a403cSLoc Ho unsigned long alignmask = crypto_ahash_alignmask(tfm); 53*004a403cSLoc Ho 54*004a403cSLoc Ho if ((unsigned long)key & alignmask) 55*004a403cSLoc Ho return ahash_setkey_unaligned(tfm, key, keylen); 56*004a403cSLoc Ho 57*004a403cSLoc Ho return ahash->setkey(tfm, key, keylen); 58*004a403cSLoc Ho } 59*004a403cSLoc Ho 60*004a403cSLoc Ho static unsigned int crypto_ahash_ctxsize(struct crypto_alg *alg, u32 type, 61*004a403cSLoc Ho u32 mask) 62*004a403cSLoc Ho { 63*004a403cSLoc Ho return alg->cra_ctxsize; 64*004a403cSLoc Ho } 65*004a403cSLoc Ho 66*004a403cSLoc Ho static int crypto_init_ahash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 67*004a403cSLoc Ho { 68*004a403cSLoc Ho struct ahash_alg *alg = &tfm->__crt_alg->cra_ahash; 69*004a403cSLoc Ho struct ahash_tfm *crt = &tfm->crt_ahash; 70*004a403cSLoc Ho 71*004a403cSLoc Ho if (alg->digestsize > crypto_tfm_alg_blocksize(tfm)) 72*004a403cSLoc Ho return -EINVAL; 73*004a403cSLoc Ho 74*004a403cSLoc Ho crt->init = alg->init; 75*004a403cSLoc Ho crt->update = alg->update; 76*004a403cSLoc Ho crt->final = alg->final; 77*004a403cSLoc Ho crt->digest = alg->digest; 78*004a403cSLoc Ho crt->setkey = ahash_setkey; 79*004a403cSLoc Ho crt->base = __crypto_ahash_cast(tfm); 80*004a403cSLoc Ho crt->digestsize = alg->digestsize; 81*004a403cSLoc Ho 82*004a403cSLoc Ho return 0; 83*004a403cSLoc Ho } 84*004a403cSLoc Ho 85*004a403cSLoc Ho static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) 86*004a403cSLoc Ho __attribute__ ((unused)); 87*004a403cSLoc Ho static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) 88*004a403cSLoc Ho { 89*004a403cSLoc Ho seq_printf(m, "type : ahash\n"); 90*004a403cSLoc Ho seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? 91*004a403cSLoc Ho "yes" : "no"); 92*004a403cSLoc Ho seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 93*004a403cSLoc Ho seq_printf(m, "digestsize : %u\n", alg->cra_hash.digestsize); 94*004a403cSLoc Ho } 95*004a403cSLoc Ho 96*004a403cSLoc Ho const struct crypto_type crypto_ahash_type = { 97*004a403cSLoc Ho .ctxsize = crypto_ahash_ctxsize, 98*004a403cSLoc Ho .init = crypto_init_ahash_ops, 99*004a403cSLoc Ho #ifdef CONFIG_PROC_FS 100*004a403cSLoc Ho .show = crypto_ahash_show, 101*004a403cSLoc Ho #endif 102*004a403cSLoc Ho }; 103*004a403cSLoc Ho EXPORT_SYMBOL_GPL(crypto_ahash_type); 104*004a403cSLoc Ho 105*004a403cSLoc Ho MODULE_LICENSE("GPL"); 106*004a403cSLoc Ho MODULE_DESCRIPTION("Asynchronous cryptographic hash type"); 107