at v2.6.24-rc4 109 lines 3.1 kB view raw
1/* 2 * Asynchronous block chaining cipher operations. 3 * 4 * This is the asynchronous version of blkcipher.c indicating completion 5 * via a callback. 6 * 7 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 */ 15 16#include <crypto/algapi.h> 17#include <linux/errno.h> 18#include <linux/init.h> 19#include <linux/kernel.h> 20#include <linux/module.h> 21#include <linux/slab.h> 22#include <linux/seq_file.h> 23 24static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, 25 unsigned int keylen) 26{ 27 struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); 28 unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); 29 int ret; 30 u8 *buffer, *alignbuffer; 31 unsigned long absize; 32 33 absize = keylen + alignmask; 34 buffer = kmalloc(absize, GFP_ATOMIC); 35 if (!buffer) 36 return -ENOMEM; 37 38 alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 39 memcpy(alignbuffer, key, keylen); 40 ret = cipher->setkey(tfm, alignbuffer, keylen); 41 memset(alignbuffer, 0, keylen); 42 kfree(buffer); 43 return ret; 44} 45 46static int setkey(struct crypto_ablkcipher *tfm, const u8 *key, 47 unsigned int keylen) 48{ 49 struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); 50 unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); 51 52 if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { 53 crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 54 return -EINVAL; 55 } 56 57 if ((unsigned long)key & alignmask) 58 return setkey_unaligned(tfm, key, keylen); 59 60 return cipher->setkey(tfm, key, keylen); 61} 62 63static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type, 64 u32 mask) 65{ 66 return alg->cra_ctxsize; 67} 68 69static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type, 70 u32 mask) 71{ 72 struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher; 73 struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher; 74 75 if (alg->ivsize > PAGE_SIZE / 8) 76 return -EINVAL; 77 78 crt->setkey = setkey; 79 crt->encrypt = alg->encrypt; 80 crt->decrypt = alg->decrypt; 81 crt->ivsize = alg->ivsize; 82 83 return 0; 84} 85 86static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg) 87 __attribute__ ((unused)); 88static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg) 89{ 90 struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher; 91 92 seq_printf(m, "type : ablkcipher\n"); 93 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 94 seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); 95 seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); 96 seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); 97} 98 99const struct crypto_type crypto_ablkcipher_type = { 100 .ctxsize = crypto_ablkcipher_ctxsize, 101 .init = crypto_init_ablkcipher_ops, 102#ifdef CONFIG_PROC_FS 103 .show = crypto_ablkcipher_show, 104#endif 105}; 106EXPORT_SYMBOL_GPL(crypto_ablkcipher_type); 107 108MODULE_LICENSE("GPL"); 109MODULE_DESCRIPTION("Asynchronous block chaining cipher type");