1333b0d7eSKazunori MIYAZAWA /* 2333b0d7eSKazunori MIYAZAWA * Copyright (C)2006 USAGI/WIDE Project 3333b0d7eSKazunori MIYAZAWA * 4333b0d7eSKazunori MIYAZAWA * This program is free software; you can redistribute it and/or modify 5333b0d7eSKazunori MIYAZAWA * it under the terms of the GNU General Public License as published by 6333b0d7eSKazunori MIYAZAWA * the Free Software Foundation; either version 2 of the License, or 7333b0d7eSKazunori MIYAZAWA * (at your option) any later version. 8333b0d7eSKazunori MIYAZAWA * 9333b0d7eSKazunori MIYAZAWA * This program is distributed in the hope that it will be useful, 10333b0d7eSKazunori MIYAZAWA * but WITHOUT ANY WARRANTY; without even the implied warranty of 11333b0d7eSKazunori MIYAZAWA * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12333b0d7eSKazunori MIYAZAWA * GNU General Public License for more details. 13333b0d7eSKazunori MIYAZAWA * 14333b0d7eSKazunori MIYAZAWA * You should have received a copy of the GNU General Public License 15333b0d7eSKazunori MIYAZAWA * along with this program; if not, write to the Free Software 16333b0d7eSKazunori MIYAZAWA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17333b0d7eSKazunori MIYAZAWA * 18333b0d7eSKazunori MIYAZAWA * Author: 19333b0d7eSKazunori MIYAZAWA * Kazunori Miyazawa <miyazawa@linux-ipv6.org> 20333b0d7eSKazunori MIYAZAWA */ 21333b0d7eSKazunori MIYAZAWA 22333b0d7eSKazunori MIYAZAWA #include <linux/crypto.h> 23333b0d7eSKazunori MIYAZAWA #include <linux/err.h> 24fb469840SHerbert Xu #include <linux/hardirq.h> 25333b0d7eSKazunori MIYAZAWA #include <linux/kernel.h> 26333b0d7eSKazunori MIYAZAWA #include <linux/mm.h> 27333b0d7eSKazunori MIYAZAWA #include <linux/rtnetlink.h> 28333b0d7eSKazunori MIYAZAWA #include <linux/slab.h> 29333b0d7eSKazunori MIYAZAWA #include <linux/scatterlist.h> 30333b0d7eSKazunori MIYAZAWA #include "internal.h" 31333b0d7eSKazunori MIYAZAWA 325b37538aSAdrian Bunk static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101, 33333b0d7eSKazunori MIYAZAWA 0x02020202, 0x02020202, 0x02020202, 0x02020202, 34333b0d7eSKazunori MIYAZAWA 0x03030303, 0x03030303, 0x03030303, 0x03030303}; 35333b0d7eSKazunori MIYAZAWA /* 36333b0d7eSKazunori MIYAZAWA * +------------------------ 37333b0d7eSKazunori MIYAZAWA * | <parent tfm> 38333b0d7eSKazunori MIYAZAWA * +------------------------ 39333b0d7eSKazunori MIYAZAWA * | crypto_xcbc_ctx 40333b0d7eSKazunori MIYAZAWA * +------------------------ 41333b0d7eSKazunori MIYAZAWA * | odds (block size) 42333b0d7eSKazunori MIYAZAWA * +------------------------ 43333b0d7eSKazunori MIYAZAWA * | prev (block size) 44333b0d7eSKazunori MIYAZAWA * +------------------------ 45333b0d7eSKazunori MIYAZAWA * | key (block size) 46333b0d7eSKazunori MIYAZAWA * +------------------------ 47333b0d7eSKazunori MIYAZAWA * | consts (block size * 3) 48333b0d7eSKazunori MIYAZAWA * +------------------------ 49333b0d7eSKazunori MIYAZAWA */ 50333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx { 516b701ddeSHerbert Xu struct crypto_cipher *child; 52333b0d7eSKazunori MIYAZAWA u8 *odds; 53333b0d7eSKazunori MIYAZAWA u8 *prev; 54333b0d7eSKazunori MIYAZAWA u8 *key; 55333b0d7eSKazunori MIYAZAWA u8 *consts; 56333b0d7eSKazunori MIYAZAWA void (*xor)(u8 *a, const u8 *b, unsigned int bs); 57333b0d7eSKazunori MIYAZAWA unsigned int keylen; 58333b0d7eSKazunori MIYAZAWA unsigned int len; 59333b0d7eSKazunori MIYAZAWA }; 60333b0d7eSKazunori MIYAZAWA 61333b0d7eSKazunori MIYAZAWA static void xor_128(u8 *a, const u8 *b, unsigned int bs) 62333b0d7eSKazunori MIYAZAWA { 63333b0d7eSKazunori MIYAZAWA ((u32 *)a)[0] ^= ((u32 *)b)[0]; 64333b0d7eSKazunori MIYAZAWA ((u32 *)a)[1] ^= ((u32 *)b)[1]; 65333b0d7eSKazunori MIYAZAWA ((u32 *)a)[2] ^= ((u32 *)b)[2]; 66333b0d7eSKazunori MIYAZAWA ((u32 *)a)[3] ^= ((u32 *)b)[3]; 67333b0d7eSKazunori MIYAZAWA } 68333b0d7eSKazunori MIYAZAWA 69333b0d7eSKazunori MIYAZAWA static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent, 70333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx) 71333b0d7eSKazunori MIYAZAWA { 72333b0d7eSKazunori MIYAZAWA int bs = crypto_hash_blocksize(parent); 73333b0d7eSKazunori MIYAZAWA int err = 0; 74333b0d7eSKazunori MIYAZAWA u8 key1[bs]; 75333b0d7eSKazunori MIYAZAWA 76333b0d7eSKazunori MIYAZAWA if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen))) 77333b0d7eSKazunori MIYAZAWA return err; 78333b0d7eSKazunori MIYAZAWA 796b701ddeSHerbert Xu crypto_cipher_encrypt_one(ctx->child, key1, ctx->consts); 80333b0d7eSKazunori MIYAZAWA 81333b0d7eSKazunori MIYAZAWA return crypto_cipher_setkey(ctx->child, key1, bs); 82333b0d7eSKazunori MIYAZAWA } 83333b0d7eSKazunori MIYAZAWA 84333b0d7eSKazunori MIYAZAWA static int crypto_xcbc_digest_setkey(struct crypto_hash *parent, 85333b0d7eSKazunori MIYAZAWA const u8 *inkey, unsigned int keylen) 86333b0d7eSKazunori MIYAZAWA { 87333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); 88333b0d7eSKazunori MIYAZAWA 896b701ddeSHerbert Xu if (keylen != crypto_cipher_blocksize(ctx->child)) 90333b0d7eSKazunori MIYAZAWA return -EINVAL; 91333b0d7eSKazunori MIYAZAWA 92333b0d7eSKazunori MIYAZAWA ctx->keylen = keylen; 93333b0d7eSKazunori MIYAZAWA memcpy(ctx->key, inkey, keylen); 94333b0d7eSKazunori MIYAZAWA ctx->consts = (u8*)ks; 95333b0d7eSKazunori MIYAZAWA 96333b0d7eSKazunori MIYAZAWA return _crypto_xcbc_digest_setkey(parent, ctx); 97333b0d7eSKazunori MIYAZAWA } 98333b0d7eSKazunori MIYAZAWA 995b37538aSAdrian Bunk static int crypto_xcbc_digest_init(struct hash_desc *pdesc) 100333b0d7eSKazunori MIYAZAWA { 101333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(pdesc->tfm); 102333b0d7eSKazunori MIYAZAWA int bs = crypto_hash_blocksize(pdesc->tfm); 103333b0d7eSKazunori MIYAZAWA 104333b0d7eSKazunori MIYAZAWA ctx->len = 0; 105333b0d7eSKazunori MIYAZAWA memset(ctx->odds, 0, bs); 106333b0d7eSKazunori MIYAZAWA memset(ctx->prev, 0, bs); 107333b0d7eSKazunori MIYAZAWA 108333b0d7eSKazunori MIYAZAWA return 0; 109333b0d7eSKazunori MIYAZAWA } 110333b0d7eSKazunori MIYAZAWA 111fb469840SHerbert Xu static int crypto_xcbc_digest_update2(struct hash_desc *pdesc, 1125b37538aSAdrian Bunk struct scatterlist *sg, 1135b37538aSAdrian Bunk unsigned int nbytes) 114333b0d7eSKazunori MIYAZAWA { 115333b0d7eSKazunori MIYAZAWA struct crypto_hash *parent = pdesc->tfm; 116333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); 1176b701ddeSHerbert Xu struct crypto_cipher *tfm = ctx->child; 118333b0d7eSKazunori MIYAZAWA int bs = crypto_hash_blocksize(parent); 119333b0d7eSKazunori MIYAZAWA unsigned int i = 0; 120333b0d7eSKazunori MIYAZAWA 121333b0d7eSKazunori MIYAZAWA do { 122333b0d7eSKazunori MIYAZAWA 123333b0d7eSKazunori MIYAZAWA struct page *pg = sg[i].page; 124333b0d7eSKazunori MIYAZAWA unsigned int offset = sg[i].offset; 125333b0d7eSKazunori MIYAZAWA unsigned int slen = sg[i].length; 126333b0d7eSKazunori MIYAZAWA 127333b0d7eSKazunori MIYAZAWA while (slen > 0) { 128333b0d7eSKazunori MIYAZAWA unsigned int len = min(slen, ((unsigned int)(PAGE_SIZE)) - offset); 129333b0d7eSKazunori MIYAZAWA char *p = crypto_kmap(pg, 0) + offset; 130333b0d7eSKazunori MIYAZAWA 131333b0d7eSKazunori MIYAZAWA /* checking the data can fill the block */ 132333b0d7eSKazunori MIYAZAWA if ((ctx->len + len) <= bs) { 133333b0d7eSKazunori MIYAZAWA memcpy(ctx->odds + ctx->len, p, len); 134333b0d7eSKazunori MIYAZAWA ctx->len += len; 135333b0d7eSKazunori MIYAZAWA slen -= len; 136333b0d7eSKazunori MIYAZAWA 137333b0d7eSKazunori MIYAZAWA /* checking the rest of the page */ 138333b0d7eSKazunori MIYAZAWA if (len + offset >= PAGE_SIZE) { 139333b0d7eSKazunori MIYAZAWA offset = 0; 140333b0d7eSKazunori MIYAZAWA pg++; 141333b0d7eSKazunori MIYAZAWA } else 142333b0d7eSKazunori MIYAZAWA offset += len; 143333b0d7eSKazunori MIYAZAWA 144333b0d7eSKazunori MIYAZAWA crypto_kunmap(p, 0); 1456b701ddeSHerbert Xu crypto_yield(pdesc->flags); 146333b0d7eSKazunori MIYAZAWA continue; 147333b0d7eSKazunori MIYAZAWA } 148333b0d7eSKazunori MIYAZAWA 149333b0d7eSKazunori MIYAZAWA /* filling odds with new data and encrypting it */ 150333b0d7eSKazunori MIYAZAWA memcpy(ctx->odds + ctx->len, p, bs - ctx->len); 151333b0d7eSKazunori MIYAZAWA len -= bs - ctx->len; 152333b0d7eSKazunori MIYAZAWA p += bs - ctx->len; 153333b0d7eSKazunori MIYAZAWA 154333b0d7eSKazunori MIYAZAWA ctx->xor(ctx->prev, ctx->odds, bs); 1556b701ddeSHerbert Xu crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev); 156333b0d7eSKazunori MIYAZAWA 157333b0d7eSKazunori MIYAZAWA /* clearing the length */ 158333b0d7eSKazunori MIYAZAWA ctx->len = 0; 159333b0d7eSKazunori MIYAZAWA 160333b0d7eSKazunori MIYAZAWA /* encrypting the rest of data */ 161333b0d7eSKazunori MIYAZAWA while (len > bs) { 162333b0d7eSKazunori MIYAZAWA ctx->xor(ctx->prev, p, bs); 1636b701ddeSHerbert Xu crypto_cipher_encrypt_one(tfm, ctx->prev, 1646b701ddeSHerbert Xu ctx->prev); 165333b0d7eSKazunori MIYAZAWA p += bs; 166333b0d7eSKazunori MIYAZAWA len -= bs; 167333b0d7eSKazunori MIYAZAWA } 168333b0d7eSKazunori MIYAZAWA 169333b0d7eSKazunori MIYAZAWA /* keeping the surplus of blocksize */ 170333b0d7eSKazunori MIYAZAWA if (len) { 171333b0d7eSKazunori MIYAZAWA memcpy(ctx->odds, p, len); 172333b0d7eSKazunori MIYAZAWA ctx->len = len; 173333b0d7eSKazunori MIYAZAWA } 174333b0d7eSKazunori MIYAZAWA crypto_kunmap(p, 0); 1756b701ddeSHerbert Xu crypto_yield(pdesc->flags); 176333b0d7eSKazunori MIYAZAWA slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset); 177333b0d7eSKazunori MIYAZAWA offset = 0; 178333b0d7eSKazunori MIYAZAWA pg++; 179333b0d7eSKazunori MIYAZAWA } 180333b0d7eSKazunori MIYAZAWA nbytes-=sg[i].length; 181333b0d7eSKazunori MIYAZAWA i++; 182333b0d7eSKazunori MIYAZAWA } while (nbytes>0); 183333b0d7eSKazunori MIYAZAWA 184333b0d7eSKazunori MIYAZAWA return 0; 185333b0d7eSKazunori MIYAZAWA } 186333b0d7eSKazunori MIYAZAWA 187fb469840SHerbert Xu static int crypto_xcbc_digest_update(struct hash_desc *pdesc, 188fb469840SHerbert Xu struct scatterlist *sg, 189fb469840SHerbert Xu unsigned int nbytes) 190fb469840SHerbert Xu { 191fb469840SHerbert Xu if (WARN_ON_ONCE(in_irq())) 192fb469840SHerbert Xu return -EDEADLK; 193fb469840SHerbert Xu return crypto_xcbc_digest_update2(pdesc, sg, nbytes); 194fb469840SHerbert Xu } 195fb469840SHerbert Xu 1965b37538aSAdrian Bunk static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out) 197333b0d7eSKazunori MIYAZAWA { 198333b0d7eSKazunori MIYAZAWA struct crypto_hash *parent = pdesc->tfm; 199333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); 2006b701ddeSHerbert Xu struct crypto_cipher *tfm = ctx->child; 201333b0d7eSKazunori MIYAZAWA int bs = crypto_hash_blocksize(parent); 202333b0d7eSKazunori MIYAZAWA int err = 0; 203333b0d7eSKazunori MIYAZAWA 204333b0d7eSKazunori MIYAZAWA if (ctx->len == bs) { 205333b0d7eSKazunori MIYAZAWA u8 key2[bs]; 206333b0d7eSKazunori MIYAZAWA 207333b0d7eSKazunori MIYAZAWA if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) 208333b0d7eSKazunori MIYAZAWA return err; 209333b0d7eSKazunori MIYAZAWA 2106b701ddeSHerbert Xu crypto_cipher_encrypt_one(tfm, key2, 2116b701ddeSHerbert Xu (u8 *)(ctx->consts + bs)); 212333b0d7eSKazunori MIYAZAWA 213333b0d7eSKazunori MIYAZAWA ctx->xor(ctx->prev, ctx->odds, bs); 214333b0d7eSKazunori MIYAZAWA ctx->xor(ctx->prev, key2, bs); 215333b0d7eSKazunori MIYAZAWA _crypto_xcbc_digest_setkey(parent, ctx); 216333b0d7eSKazunori MIYAZAWA 2176b701ddeSHerbert Xu crypto_cipher_encrypt_one(tfm, out, ctx->prev); 218333b0d7eSKazunori MIYAZAWA } else { 219333b0d7eSKazunori MIYAZAWA u8 key3[bs]; 220333b0d7eSKazunori MIYAZAWA unsigned int rlen; 221333b0d7eSKazunori MIYAZAWA u8 *p = ctx->odds + ctx->len; 222333b0d7eSKazunori MIYAZAWA *p = 0x80; 223333b0d7eSKazunori MIYAZAWA p++; 224333b0d7eSKazunori MIYAZAWA 225333b0d7eSKazunori MIYAZAWA rlen = bs - ctx->len -1; 226333b0d7eSKazunori MIYAZAWA if (rlen) 227333b0d7eSKazunori MIYAZAWA memset(p, 0, rlen); 228333b0d7eSKazunori MIYAZAWA 229333b0d7eSKazunori MIYAZAWA if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) 230333b0d7eSKazunori MIYAZAWA return err; 231333b0d7eSKazunori MIYAZAWA 2326b701ddeSHerbert Xu crypto_cipher_encrypt_one(tfm, key3, 2336b701ddeSHerbert Xu (u8 *)(ctx->consts + bs * 2)); 234333b0d7eSKazunori MIYAZAWA 235333b0d7eSKazunori MIYAZAWA ctx->xor(ctx->prev, ctx->odds, bs); 236333b0d7eSKazunori MIYAZAWA ctx->xor(ctx->prev, key3, bs); 237333b0d7eSKazunori MIYAZAWA 238333b0d7eSKazunori MIYAZAWA _crypto_xcbc_digest_setkey(parent, ctx); 239333b0d7eSKazunori MIYAZAWA 2406b701ddeSHerbert Xu crypto_cipher_encrypt_one(tfm, out, ctx->prev); 241333b0d7eSKazunori MIYAZAWA } 242333b0d7eSKazunori MIYAZAWA 243333b0d7eSKazunori MIYAZAWA return 0; 244333b0d7eSKazunori MIYAZAWA } 245333b0d7eSKazunori MIYAZAWA 246333b0d7eSKazunori MIYAZAWA static int crypto_xcbc_digest(struct hash_desc *pdesc, 247333b0d7eSKazunori MIYAZAWA struct scatterlist *sg, unsigned int nbytes, u8 *out) 248333b0d7eSKazunori MIYAZAWA { 249fb469840SHerbert Xu if (WARN_ON_ONCE(in_irq())) 250fb469840SHerbert Xu return -EDEADLK; 251fb469840SHerbert Xu 252333b0d7eSKazunori MIYAZAWA crypto_xcbc_digest_init(pdesc); 253fb469840SHerbert Xu crypto_xcbc_digest_update2(pdesc, sg, nbytes); 254333b0d7eSKazunori MIYAZAWA return crypto_xcbc_digest_final(pdesc, out); 255333b0d7eSKazunori MIYAZAWA } 256333b0d7eSKazunori MIYAZAWA 257333b0d7eSKazunori MIYAZAWA static int xcbc_init_tfm(struct crypto_tfm *tfm) 258333b0d7eSKazunori MIYAZAWA { 2592e306ee0SHerbert Xu struct crypto_cipher *cipher; 260333b0d7eSKazunori MIYAZAWA struct crypto_instance *inst = (void *)tfm->__crt_alg; 261333b0d7eSKazunori MIYAZAWA struct crypto_spawn *spawn = crypto_instance_ctx(inst); 262333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm)); 263333b0d7eSKazunori MIYAZAWA int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm)); 264333b0d7eSKazunori MIYAZAWA 2652e306ee0SHerbert Xu cipher = crypto_spawn_cipher(spawn); 2662e306ee0SHerbert Xu if (IS_ERR(cipher)) 2672e306ee0SHerbert Xu return PTR_ERR(cipher); 268333b0d7eSKazunori MIYAZAWA 269333b0d7eSKazunori MIYAZAWA switch(bs) { 270333b0d7eSKazunori MIYAZAWA case 16: 271333b0d7eSKazunori MIYAZAWA ctx->xor = xor_128; 272333b0d7eSKazunori MIYAZAWA break; 273333b0d7eSKazunori MIYAZAWA default: 274333b0d7eSKazunori MIYAZAWA return -EINVAL; 275333b0d7eSKazunori MIYAZAWA } 276333b0d7eSKazunori MIYAZAWA 2772e306ee0SHerbert Xu ctx->child = cipher; 278333b0d7eSKazunori MIYAZAWA ctx->odds = (u8*)(ctx+1); 279333b0d7eSKazunori MIYAZAWA ctx->prev = ctx->odds + bs; 280333b0d7eSKazunori MIYAZAWA ctx->key = ctx->prev + bs; 281333b0d7eSKazunori MIYAZAWA 282333b0d7eSKazunori MIYAZAWA return 0; 283333b0d7eSKazunori MIYAZAWA }; 284333b0d7eSKazunori MIYAZAWA 285333b0d7eSKazunori MIYAZAWA static void xcbc_exit_tfm(struct crypto_tfm *tfm) 286333b0d7eSKazunori MIYAZAWA { 287333b0d7eSKazunori MIYAZAWA struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm)); 288333b0d7eSKazunori MIYAZAWA crypto_free_cipher(ctx->child); 289333b0d7eSKazunori MIYAZAWA } 290333b0d7eSKazunori MIYAZAWA 291*ebc610e5SHerbert Xu static struct crypto_instance *xcbc_alloc(struct rtattr **tb) 292333b0d7eSKazunori MIYAZAWA { 293333b0d7eSKazunori MIYAZAWA struct crypto_instance *inst; 294333b0d7eSKazunori MIYAZAWA struct crypto_alg *alg; 295*ebc610e5SHerbert Xu int err; 296*ebc610e5SHerbert Xu 297*ebc610e5SHerbert Xu err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH); 298*ebc610e5SHerbert Xu if (err) 299*ebc610e5SHerbert Xu return ERR_PTR(err); 300*ebc610e5SHerbert Xu 301*ebc610e5SHerbert Xu alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, 302*ebc610e5SHerbert Xu CRYPTO_ALG_TYPE_MASK); 303333b0d7eSKazunori MIYAZAWA if (IS_ERR(alg)) 304333b0d7eSKazunori MIYAZAWA return ERR_PTR(PTR_ERR(alg)); 305333b0d7eSKazunori MIYAZAWA 306333b0d7eSKazunori MIYAZAWA switch(alg->cra_blocksize) { 307333b0d7eSKazunori MIYAZAWA case 16: 308333b0d7eSKazunori MIYAZAWA break; 309333b0d7eSKazunori MIYAZAWA default: 310333b0d7eSKazunori MIYAZAWA return ERR_PTR(PTR_ERR(alg)); 311333b0d7eSKazunori MIYAZAWA } 312333b0d7eSKazunori MIYAZAWA 313333b0d7eSKazunori MIYAZAWA inst = crypto_alloc_instance("xcbc", alg); 314333b0d7eSKazunori MIYAZAWA if (IS_ERR(inst)) 315333b0d7eSKazunori MIYAZAWA goto out_put_alg; 316333b0d7eSKazunori MIYAZAWA 317333b0d7eSKazunori MIYAZAWA inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH; 318333b0d7eSKazunori MIYAZAWA inst->alg.cra_priority = alg->cra_priority; 319333b0d7eSKazunori MIYAZAWA inst->alg.cra_blocksize = alg->cra_blocksize; 320333b0d7eSKazunori MIYAZAWA inst->alg.cra_alignmask = alg->cra_alignmask; 321333b0d7eSKazunori MIYAZAWA inst->alg.cra_type = &crypto_hash_type; 322333b0d7eSKazunori MIYAZAWA 323333b0d7eSKazunori MIYAZAWA inst->alg.cra_hash.digestsize = 324333b0d7eSKazunori MIYAZAWA (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == 325333b0d7eSKazunori MIYAZAWA CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize : 326333b0d7eSKazunori MIYAZAWA alg->cra_blocksize; 327333b0d7eSKazunori MIYAZAWA inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) + 328333b0d7eSKazunori MIYAZAWA ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *)); 329333b0d7eSKazunori MIYAZAWA inst->alg.cra_init = xcbc_init_tfm; 330333b0d7eSKazunori MIYAZAWA inst->alg.cra_exit = xcbc_exit_tfm; 331333b0d7eSKazunori MIYAZAWA 332333b0d7eSKazunori MIYAZAWA inst->alg.cra_hash.init = crypto_xcbc_digest_init; 333333b0d7eSKazunori MIYAZAWA inst->alg.cra_hash.update = crypto_xcbc_digest_update; 334333b0d7eSKazunori MIYAZAWA inst->alg.cra_hash.final = crypto_xcbc_digest_final; 335333b0d7eSKazunori MIYAZAWA inst->alg.cra_hash.digest = crypto_xcbc_digest; 336333b0d7eSKazunori MIYAZAWA inst->alg.cra_hash.setkey = crypto_xcbc_digest_setkey; 337333b0d7eSKazunori MIYAZAWA 338333b0d7eSKazunori MIYAZAWA out_put_alg: 339333b0d7eSKazunori MIYAZAWA crypto_mod_put(alg); 340333b0d7eSKazunori MIYAZAWA return inst; 341333b0d7eSKazunori MIYAZAWA } 342333b0d7eSKazunori MIYAZAWA 343333b0d7eSKazunori MIYAZAWA static void xcbc_free(struct crypto_instance *inst) 344333b0d7eSKazunori MIYAZAWA { 345333b0d7eSKazunori MIYAZAWA crypto_drop_spawn(crypto_instance_ctx(inst)); 346333b0d7eSKazunori MIYAZAWA kfree(inst); 347333b0d7eSKazunori MIYAZAWA } 348333b0d7eSKazunori MIYAZAWA 349333b0d7eSKazunori MIYAZAWA static struct crypto_template crypto_xcbc_tmpl = { 350333b0d7eSKazunori MIYAZAWA .name = "xcbc", 351333b0d7eSKazunori MIYAZAWA .alloc = xcbc_alloc, 352333b0d7eSKazunori MIYAZAWA .free = xcbc_free, 353333b0d7eSKazunori MIYAZAWA .module = THIS_MODULE, 354333b0d7eSKazunori MIYAZAWA }; 355333b0d7eSKazunori MIYAZAWA 356333b0d7eSKazunori MIYAZAWA static int __init crypto_xcbc_module_init(void) 357333b0d7eSKazunori MIYAZAWA { 358333b0d7eSKazunori MIYAZAWA return crypto_register_template(&crypto_xcbc_tmpl); 359333b0d7eSKazunori MIYAZAWA } 360333b0d7eSKazunori MIYAZAWA 361333b0d7eSKazunori MIYAZAWA static void __exit crypto_xcbc_module_exit(void) 362333b0d7eSKazunori MIYAZAWA { 363333b0d7eSKazunori MIYAZAWA crypto_unregister_template(&crypto_xcbc_tmpl); 364333b0d7eSKazunori MIYAZAWA } 365333b0d7eSKazunori MIYAZAWA 366333b0d7eSKazunori MIYAZAWA module_init(crypto_xcbc_module_init); 367333b0d7eSKazunori MIYAZAWA module_exit(crypto_xcbc_module_exit); 368333b0d7eSKazunori MIYAZAWA 369333b0d7eSKazunori MIYAZAWA MODULE_LICENSE("GPL"); 370333b0d7eSKazunori MIYAZAWA MODULE_DESCRIPTION("XCBC keyed hash algorithm"); 371