#include #include #include #include static struct tasklet_struct ablk_tasklet; struct ablk_ctx { char key[16]; }; static void ablk_doit( unsigned long data ) { int error = 0, i; struct ablkcipher_request *req = (struct ablkcipher_request *) data; char *src, *dst; struct ablk_ctx *ctx; printk("ablk_doit(%p)\n", req ); src = sg_virt( req->src ); dst = sg_virt( req->dst ); ctx = crypto_tfm_ctx(req->base.tfm); for( i=0; inbytes; i++ ) dst[i] = src[i] ^ ctx->key[i]; req->base.complete(&req->base, error); } static int ablk_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { struct ablk_ctx *ctx = crypto_tfm_ctx(&tfm->base); printk("ablk_setkey( %p, %d )\n", key, keylen ); if (keylen == 16) { memcpy(ctx->key, key, keylen); return 0; } return -EINVAL; } int ablk_decrypt(struct ablkcipher_request *req ) { printk("ablk_decrypt( %p )\n", req); tasklet_init( &ablk_tasklet, ablk_doit, (unsigned long)req ); tasklet_schedule( &ablk_tasklet ); return -EINPROGRESS; } int ablk_encrypt(struct ablkcipher_request *req ) { printk("ablk_encrypt( %p )\n", req); tasklet_init( &ablk_tasklet, ablk_doit, (unsigned long)req ); tasklet_schedule( &ablk_tasklet ); return -EINPROGRESS; } static struct crypto_alg ablkcipher_ablk = { .cra_list = LIST_HEAD_INIT(ablkcipher_ablk.cra_list), .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, .cra_blocksize = 16, .cra_ctxsize = sizeof(struct ablk_ctx), .cra_priority = 100, .cra_name = "ablk", .cra_type = &crypto_ablkcipher_type, .cra_u = { .ablkcipher = { .setkey = ablk_setkey, .encrypt = ablk_encrypt, .decrypt = ablk_decrypt, .geniv = NULL, .min_keysize = 0, .max_keysize = 16, .ivsize = 0, }, } }; static int __init crypto_ablk_mod_init(void) { printk("crypto_ablk_mod_init()\n"); return crypto_register_alg(&ablkcipher_ablk); } static void __exit crypto_ablk_mod_exit(void) { printk("crypto_ablk_mod_exit()\n"); tasklet_kill( &ablk_tasklet ); crypto_unregister_alg(&ablkcipher_ablk); } module_init(crypto_ablk_mod_init); module_exit(crypto_ablk_mod_exit); MODULE_LICENSE("GPL");