1da7f033dSHerbert Xu /* 2da7f033dSHerbert Xu * Create default crypto algorithm instances. 3da7f033dSHerbert Xu * 4da7f033dSHerbert Xu * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 5da7f033dSHerbert Xu * 6da7f033dSHerbert Xu * This program is free software; you can redistribute it and/or modify it 7da7f033dSHerbert Xu * under the terms of the GNU General Public License as published by the Free 8da7f033dSHerbert Xu * Software Foundation; either version 2 of the License, or (at your option) 9da7f033dSHerbert Xu * any later version. 10da7f033dSHerbert Xu * 11da7f033dSHerbert Xu */ 12da7f033dSHerbert Xu 136fe4a28dSHerbert Xu #include <crypto/internal/aead.h> 1439871037SHerbert Xu #include <linux/completion.h> 15da7f033dSHerbert Xu #include <linux/ctype.h> 16da7f033dSHerbert Xu #include <linux/err.h> 17da7f033dSHerbert Xu #include <linux/init.h> 18da7f033dSHerbert Xu #include <linux/kthread.h> 19da7f033dSHerbert Xu #include <linux/module.h> 20da7f033dSHerbert Xu #include <linux/notifier.h> 21da7f033dSHerbert Xu #include <linux/rtnetlink.h> 22da7f033dSHerbert Xu #include <linux/sched.h> 235a0e3ad6STejun Heo #include <linux/slab.h> 24da7f033dSHerbert Xu #include <linux/string.h> 25da7f033dSHerbert Xu 26da7f033dSHerbert Xu #include "internal.h" 27da7f033dSHerbert Xu 28da7f033dSHerbert Xu struct cryptomgr_param { 29da7f033dSHerbert Xu struct rtattr *tb[CRYPTO_MAX_ATTRS + 2]; 30da7f033dSHerbert Xu 31da7f033dSHerbert Xu struct { 32da7f033dSHerbert Xu struct rtattr attr; 33da7f033dSHerbert Xu struct crypto_attr_type data; 34da7f033dSHerbert Xu } type; 35da7f033dSHerbert Xu 36da7f033dSHerbert Xu union { 37da7f033dSHerbert Xu struct rtattr attr; 38da7f033dSHerbert Xu struct { 39da7f033dSHerbert Xu struct rtattr attr; 40da7f033dSHerbert Xu struct crypto_attr_alg data; 41da7f033dSHerbert Xu } alg; 42da7f033dSHerbert Xu struct { 43da7f033dSHerbert Xu struct rtattr attr; 44da7f033dSHerbert Xu struct crypto_attr_u32 data; 45da7f033dSHerbert Xu } nu32; 46da7f033dSHerbert Xu } attrs[CRYPTO_MAX_ATTRS]; 47da7f033dSHerbert Xu 48da7f033dSHerbert Xu char template[CRYPTO_MAX_ALG_NAME]; 4973d3864aSHerbert Xu 50939e1779SHerbert Xu struct crypto_larval *larval; 5139871037SHerbert Xu 5273d3864aSHerbert Xu u32 otype; 5373d3864aSHerbert Xu u32 omask; 5473d3864aSHerbert Xu }; 5573d3864aSHerbert Xu 5673d3864aSHerbert Xu struct crypto_test_param { 5773d3864aSHerbert Xu char driver[CRYPTO_MAX_ALG_NAME]; 5873d3864aSHerbert Xu char alg[CRYPTO_MAX_ALG_NAME]; 5973d3864aSHerbert Xu u32 type; 60da7f033dSHerbert Xu }; 61da7f033dSHerbert Xu 62da7f033dSHerbert Xu static int cryptomgr_probe(void *data) 63da7f033dSHerbert Xu { 64da7f033dSHerbert Xu struct cryptomgr_param *param = data; 65da7f033dSHerbert Xu struct crypto_template *tmpl; 66da7f033dSHerbert Xu struct crypto_instance *inst; 67da7f033dSHerbert Xu int err; 68da7f033dSHerbert Xu 69da7f033dSHerbert Xu tmpl = crypto_lookup_template(param->template); 70da7f033dSHerbert Xu if (!tmpl) 7139871037SHerbert Xu goto out; 72da7f033dSHerbert Xu 73da7f033dSHerbert Xu do { 74f2ac72e8SHerbert Xu if (tmpl->create) { 75f2ac72e8SHerbert Xu err = tmpl->create(tmpl, param->tb); 76f2ac72e8SHerbert Xu continue; 77f2ac72e8SHerbert Xu } 78f2ac72e8SHerbert Xu 79da7f033dSHerbert Xu inst = tmpl->alloc(param->tb); 80da7f033dSHerbert Xu if (IS_ERR(inst)) 81da7f033dSHerbert Xu err = PTR_ERR(inst); 82da7f033dSHerbert Xu else if ((err = crypto_register_instance(tmpl, inst))) 83da7f033dSHerbert Xu tmpl->free(inst); 84da7f033dSHerbert Xu } while (err == -EAGAIN && !signal_pending(current)); 85da7f033dSHerbert Xu 86da7f033dSHerbert Xu crypto_tmpl_put(tmpl); 87da7f033dSHerbert Xu 88da7f033dSHerbert Xu out: 89939e1779SHerbert Xu complete_all(¶m->larval->completion); 90939e1779SHerbert Xu crypto_alg_put(¶m->larval->alg); 91da7f033dSHerbert Xu kfree(param); 92da7f033dSHerbert Xu module_put_and_exit(0); 93da7f033dSHerbert Xu } 94da7f033dSHerbert Xu 95da7f033dSHerbert Xu static int cryptomgr_schedule_probe(struct crypto_larval *larval) 96da7f033dSHerbert Xu { 97da7f033dSHerbert Xu struct task_struct *thread; 98da7f033dSHerbert Xu struct cryptomgr_param *param; 99da7f033dSHerbert Xu const char *name = larval->alg.cra_name; 100da7f033dSHerbert Xu const char *p; 101da7f033dSHerbert Xu unsigned int len; 102da7f033dSHerbert Xu int i; 103da7f033dSHerbert Xu 104da7f033dSHerbert Xu if (!try_module_get(THIS_MODULE)) 105da7f033dSHerbert Xu goto err; 106da7f033dSHerbert Xu 107da7f033dSHerbert Xu param = kzalloc(sizeof(*param), GFP_KERNEL); 108da7f033dSHerbert Xu if (!param) 109da7f033dSHerbert Xu goto err_put_module; 110da7f033dSHerbert Xu 111da7f033dSHerbert Xu for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) 112da7f033dSHerbert Xu ; 113da7f033dSHerbert Xu 114da7f033dSHerbert Xu len = p - name; 115da7f033dSHerbert Xu if (!len || *p != '(') 116da7f033dSHerbert Xu goto err_free_param; 117da7f033dSHerbert Xu 118da7f033dSHerbert Xu memcpy(param->template, name, len); 119da7f033dSHerbert Xu 120da7f033dSHerbert Xu i = 0; 121da7f033dSHerbert Xu for (;;) { 122da7f033dSHerbert Xu int notnum = 0; 123da7f033dSHerbert Xu 124da7f033dSHerbert Xu name = ++p; 125da7f033dSHerbert Xu len = 0; 126da7f033dSHerbert Xu 127da7f033dSHerbert Xu for (; isalnum(*p) || *p == '-' || *p == '_'; p++) 128da7f033dSHerbert Xu notnum |= !isdigit(*p); 129da7f033dSHerbert Xu 130da7f033dSHerbert Xu if (*p == '(') { 131da7f033dSHerbert Xu int recursion = 0; 132da7f033dSHerbert Xu 133da7f033dSHerbert Xu for (;;) { 134da7f033dSHerbert Xu if (!*++p) 135da7f033dSHerbert Xu goto err_free_param; 136da7f033dSHerbert Xu if (*p == '(') 137da7f033dSHerbert Xu recursion++; 138da7f033dSHerbert Xu else if (*p == ')' && !recursion--) 139da7f033dSHerbert Xu break; 140da7f033dSHerbert Xu } 141da7f033dSHerbert Xu 142da7f033dSHerbert Xu notnum = 1; 143da7f033dSHerbert Xu p++; 144da7f033dSHerbert Xu } 145da7f033dSHerbert Xu 146da7f033dSHerbert Xu len = p - name; 147da7f033dSHerbert Xu if (!len) 148da7f033dSHerbert Xu goto err_free_param; 149da7f033dSHerbert Xu 150da7f033dSHerbert Xu if (notnum) { 151da7f033dSHerbert Xu param->attrs[i].alg.attr.rta_len = 152da7f033dSHerbert Xu sizeof(param->attrs[i].alg); 153da7f033dSHerbert Xu param->attrs[i].alg.attr.rta_type = CRYPTOA_ALG; 154da7f033dSHerbert Xu memcpy(param->attrs[i].alg.data.name, name, len); 155da7f033dSHerbert Xu } else { 156da7f033dSHerbert Xu param->attrs[i].nu32.attr.rta_len = 157da7f033dSHerbert Xu sizeof(param->attrs[i].nu32); 158da7f033dSHerbert Xu param->attrs[i].nu32.attr.rta_type = CRYPTOA_U32; 159da7f033dSHerbert Xu param->attrs[i].nu32.data.num = 160da7f033dSHerbert Xu simple_strtol(name, NULL, 0); 161da7f033dSHerbert Xu } 162da7f033dSHerbert Xu 163da7f033dSHerbert Xu param->tb[i + 1] = ¶m->attrs[i].attr; 164da7f033dSHerbert Xu i++; 165da7f033dSHerbert Xu 166da7f033dSHerbert Xu if (i >= CRYPTO_MAX_ATTRS) 167da7f033dSHerbert Xu goto err_free_param; 168da7f033dSHerbert Xu 169da7f033dSHerbert Xu if (*p == ')') 170da7f033dSHerbert Xu break; 171da7f033dSHerbert Xu 172da7f033dSHerbert Xu if (*p != ',') 173da7f033dSHerbert Xu goto err_free_param; 174da7f033dSHerbert Xu } 175da7f033dSHerbert Xu 176da7f033dSHerbert Xu if (!i) 177da7f033dSHerbert Xu goto err_free_param; 178da7f033dSHerbert Xu 179da7f033dSHerbert Xu param->tb[i + 1] = NULL; 180da7f033dSHerbert Xu 181da7f033dSHerbert Xu param->type.attr.rta_len = sizeof(param->type); 182da7f033dSHerbert Xu param->type.attr.rta_type = CRYPTOA_TYPE; 18373d3864aSHerbert Xu param->type.data.type = larval->alg.cra_flags & ~CRYPTO_ALG_TESTED; 18473d3864aSHerbert Xu param->type.data.mask = larval->mask & ~CRYPTO_ALG_TESTED; 185da7f033dSHerbert Xu param->tb[0] = ¶m->type.attr; 186da7f033dSHerbert Xu 18773d3864aSHerbert Xu param->otype = larval->alg.cra_flags; 18873d3864aSHerbert Xu param->omask = larval->mask; 18973d3864aSHerbert Xu 190939e1779SHerbert Xu crypto_alg_get(&larval->alg); 191939e1779SHerbert Xu param->larval = larval; 19239871037SHerbert Xu 19373d3864aSHerbert Xu thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe"); 19473d3864aSHerbert Xu if (IS_ERR(thread)) 195939e1779SHerbert Xu goto err_put_larval; 19673d3864aSHerbert Xu 19739871037SHerbert Xu wait_for_completion_interruptible(&larval->completion); 19839871037SHerbert Xu 19973d3864aSHerbert Xu return NOTIFY_STOP; 20073d3864aSHerbert Xu 201939e1779SHerbert Xu err_put_larval: 202939e1779SHerbert Xu crypto_alg_put(&larval->alg); 20373d3864aSHerbert Xu err_free_param: 20473d3864aSHerbert Xu kfree(param); 20573d3864aSHerbert Xu err_put_module: 20673d3864aSHerbert Xu module_put(THIS_MODULE); 20773d3864aSHerbert Xu err: 20873d3864aSHerbert Xu return NOTIFY_OK; 20973d3864aSHerbert Xu } 21073d3864aSHerbert Xu 21173d3864aSHerbert Xu static int cryptomgr_test(void *data) 21273d3864aSHerbert Xu { 21373d3864aSHerbert Xu struct crypto_test_param *param = data; 21473d3864aSHerbert Xu u32 type = param->type; 21573d3864aSHerbert Xu int err = 0; 21673d3864aSHerbert Xu 217326a6346SHerbert Xu #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS 218326a6346SHerbert Xu goto skiptest; 219326a6346SHerbert Xu #endif 220326a6346SHerbert Xu 2216fe4a28dSHerbert Xu if (type & CRYPTO_ALG_TESTED) 22273d3864aSHerbert Xu goto skiptest; 22373d3864aSHerbert Xu 2241aa4ecd9SHerbert Xu err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED); 22573d3864aSHerbert Xu 22673d3864aSHerbert Xu skiptest: 22773d3864aSHerbert Xu crypto_alg_tested(param->driver, err); 22873d3864aSHerbert Xu 22973d3864aSHerbert Xu kfree(param); 23073d3864aSHerbert Xu module_put_and_exit(0); 23173d3864aSHerbert Xu } 23273d3864aSHerbert Xu 23373d3864aSHerbert Xu static int cryptomgr_schedule_test(struct crypto_alg *alg) 23473d3864aSHerbert Xu { 23573d3864aSHerbert Xu struct task_struct *thread; 23673d3864aSHerbert Xu struct crypto_test_param *param; 2376fe4a28dSHerbert Xu u32 type; 23873d3864aSHerbert Xu 23973d3864aSHerbert Xu if (!try_module_get(THIS_MODULE)) 24073d3864aSHerbert Xu goto err; 24173d3864aSHerbert Xu 24273d3864aSHerbert Xu param = kzalloc(sizeof(*param), GFP_KERNEL); 24373d3864aSHerbert Xu if (!param) 24473d3864aSHerbert Xu goto err_put_module; 24573d3864aSHerbert Xu 24673d3864aSHerbert Xu memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver)); 24773d3864aSHerbert Xu memcpy(param->alg, alg->cra_name, sizeof(param->alg)); 2486fe4a28dSHerbert Xu type = alg->cra_flags; 2496fe4a28dSHerbert Xu 2506fe4a28dSHerbert Xu /* This piece of crap needs to disappear into per-type test hooks. */ 2516fe4a28dSHerbert Xu if ((!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & 2526fe4a28dSHerbert Xu CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) && 2536fe4a28dSHerbert Xu ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == 2546fe4a28dSHerbert Xu CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize : 2556fe4a28dSHerbert Xu alg->cra_ablkcipher.ivsize)) || 2566fe4a28dSHerbert Xu (!((type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) && 2576fe4a28dSHerbert Xu alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize)) 2586fe4a28dSHerbert Xu type |= CRYPTO_ALG_TESTED; 2596fe4a28dSHerbert Xu 2606fe4a28dSHerbert Xu param->type = type; 26173d3864aSHerbert Xu 26273d3864aSHerbert Xu thread = kthread_run(cryptomgr_test, param, "cryptomgr_test"); 263da7f033dSHerbert Xu if (IS_ERR(thread)) 264da7f033dSHerbert Xu goto err_free_param; 265da7f033dSHerbert Xu 266da7f033dSHerbert Xu return NOTIFY_STOP; 267da7f033dSHerbert Xu 268da7f033dSHerbert Xu err_free_param: 269da7f033dSHerbert Xu kfree(param); 270da7f033dSHerbert Xu err_put_module: 271da7f033dSHerbert Xu module_put(THIS_MODULE); 272da7f033dSHerbert Xu err: 273da7f033dSHerbert Xu return NOTIFY_OK; 274da7f033dSHerbert Xu } 275da7f033dSHerbert Xu 276da7f033dSHerbert Xu static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, 277da7f033dSHerbert Xu void *data) 278da7f033dSHerbert Xu { 279da7f033dSHerbert Xu switch (msg) { 280da7f033dSHerbert Xu case CRYPTO_MSG_ALG_REQUEST: 281da7f033dSHerbert Xu return cryptomgr_schedule_probe(data); 28273d3864aSHerbert Xu case CRYPTO_MSG_ALG_REGISTER: 28373d3864aSHerbert Xu return cryptomgr_schedule_test(data); 284da7f033dSHerbert Xu } 285da7f033dSHerbert Xu 286da7f033dSHerbert Xu return NOTIFY_DONE; 287da7f033dSHerbert Xu } 288da7f033dSHerbert Xu 289da7f033dSHerbert Xu static struct notifier_block cryptomgr_notifier = { 290da7f033dSHerbert Xu .notifier_call = cryptomgr_notify, 291da7f033dSHerbert Xu }; 292da7f033dSHerbert Xu 293da7f033dSHerbert Xu static int __init cryptomgr_init(void) 294da7f033dSHerbert Xu { 295f8b0d4d0SHerbert Xu return crypto_register_notifier(&cryptomgr_notifier); 296da7f033dSHerbert Xu } 297da7f033dSHerbert Xu 298da7f033dSHerbert Xu static void __exit cryptomgr_exit(void) 299da7f033dSHerbert Xu { 300da7f033dSHerbert Xu int err = crypto_unregister_notifier(&cryptomgr_notifier); 301da7f033dSHerbert Xu BUG_ON(err); 302da7f033dSHerbert Xu } 303da7f033dSHerbert Xu 304da7f033dSHerbert Xu subsys_initcall(cryptomgr_init); 305da7f033dSHerbert Xu module_exit(cryptomgr_exit); 306da7f033dSHerbert Xu 307da7f033dSHerbert Xu MODULE_LICENSE("GPL"); 308da7f033dSHerbert Xu MODULE_DESCRIPTION("Crypto Algorithm Manager"); 309