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 13da7f033dSHerbert Xu #include <linux/crypto.h> 14da7f033dSHerbert Xu #include <linux/ctype.h> 15da7f033dSHerbert Xu #include <linux/err.h> 16da7f033dSHerbert Xu #include <linux/init.h> 17da7f033dSHerbert Xu #include <linux/kthread.h> 18da7f033dSHerbert Xu #include <linux/module.h> 19da7f033dSHerbert Xu #include <linux/notifier.h> 20da7f033dSHerbert Xu #include <linux/rtnetlink.h> 21da7f033dSHerbert Xu #include <linux/sched.h> 22da7f033dSHerbert Xu #include <linux/string.h> 23da7f033dSHerbert Xu 24da7f033dSHerbert Xu #include "internal.h" 25da7f033dSHerbert Xu 26da7f033dSHerbert Xu struct cryptomgr_param { 27da7f033dSHerbert Xu struct rtattr *tb[CRYPTO_MAX_ATTRS + 2]; 28da7f033dSHerbert Xu 29da7f033dSHerbert Xu struct { 30da7f033dSHerbert Xu struct rtattr attr; 31da7f033dSHerbert Xu struct crypto_attr_type data; 32da7f033dSHerbert Xu } type; 33da7f033dSHerbert Xu 34da7f033dSHerbert Xu union { 35da7f033dSHerbert Xu struct rtattr attr; 36da7f033dSHerbert Xu struct { 37da7f033dSHerbert Xu struct rtattr attr; 38da7f033dSHerbert Xu struct crypto_attr_alg data; 39da7f033dSHerbert Xu } alg; 40da7f033dSHerbert Xu struct { 41da7f033dSHerbert Xu struct rtattr attr; 42da7f033dSHerbert Xu struct crypto_attr_u32 data; 43da7f033dSHerbert Xu } nu32; 44da7f033dSHerbert Xu } attrs[CRYPTO_MAX_ATTRS]; 45da7f033dSHerbert Xu 46da7f033dSHerbert Xu char larval[CRYPTO_MAX_ALG_NAME]; 47da7f033dSHerbert Xu char template[CRYPTO_MAX_ALG_NAME]; 4873d3864aSHerbert Xu 4973d3864aSHerbert Xu u32 otype; 5073d3864aSHerbert Xu u32 omask; 5173d3864aSHerbert Xu }; 5273d3864aSHerbert Xu 5373d3864aSHerbert Xu struct crypto_test_param { 5473d3864aSHerbert Xu char driver[CRYPTO_MAX_ALG_NAME]; 5573d3864aSHerbert Xu char alg[CRYPTO_MAX_ALG_NAME]; 5673d3864aSHerbert Xu u32 type; 57da7f033dSHerbert Xu }; 58da7f033dSHerbert Xu 59da7f033dSHerbert Xu static int cryptomgr_probe(void *data) 60da7f033dSHerbert Xu { 61da7f033dSHerbert Xu struct cryptomgr_param *param = data; 62da7f033dSHerbert Xu struct crypto_template *tmpl; 63da7f033dSHerbert Xu struct crypto_instance *inst; 64da7f033dSHerbert Xu int err; 65da7f033dSHerbert Xu 66da7f033dSHerbert Xu tmpl = crypto_lookup_template(param->template); 67da7f033dSHerbert Xu if (!tmpl) 68da7f033dSHerbert Xu goto err; 69da7f033dSHerbert Xu 70da7f033dSHerbert Xu do { 71da7f033dSHerbert Xu inst = tmpl->alloc(param->tb); 72da7f033dSHerbert Xu if (IS_ERR(inst)) 73da7f033dSHerbert Xu err = PTR_ERR(inst); 74da7f033dSHerbert Xu else if ((err = crypto_register_instance(tmpl, inst))) 75da7f033dSHerbert Xu tmpl->free(inst); 76da7f033dSHerbert Xu } while (err == -EAGAIN && !signal_pending(current)); 77da7f033dSHerbert Xu 78da7f033dSHerbert Xu crypto_tmpl_put(tmpl); 79da7f033dSHerbert Xu 80da7f033dSHerbert Xu if (err) 81da7f033dSHerbert Xu goto err; 82da7f033dSHerbert Xu 83da7f033dSHerbert Xu out: 84da7f033dSHerbert Xu kfree(param); 85da7f033dSHerbert Xu module_put_and_exit(0); 86da7f033dSHerbert Xu 87da7f033dSHerbert Xu err: 8873d3864aSHerbert Xu crypto_larval_error(param->larval, param->otype, param->omask); 89da7f033dSHerbert Xu goto out; 90da7f033dSHerbert Xu } 91da7f033dSHerbert Xu 92da7f033dSHerbert Xu static int cryptomgr_schedule_probe(struct crypto_larval *larval) 93da7f033dSHerbert Xu { 94da7f033dSHerbert Xu struct task_struct *thread; 95da7f033dSHerbert Xu struct cryptomgr_param *param; 96da7f033dSHerbert Xu const char *name = larval->alg.cra_name; 97da7f033dSHerbert Xu const char *p; 98da7f033dSHerbert Xu unsigned int len; 99da7f033dSHerbert Xu int i; 100da7f033dSHerbert Xu 101da7f033dSHerbert Xu if (!try_module_get(THIS_MODULE)) 102da7f033dSHerbert Xu goto err; 103da7f033dSHerbert Xu 104da7f033dSHerbert Xu param = kzalloc(sizeof(*param), GFP_KERNEL); 105da7f033dSHerbert Xu if (!param) 106da7f033dSHerbert Xu goto err_put_module; 107da7f033dSHerbert Xu 108da7f033dSHerbert Xu for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) 109da7f033dSHerbert Xu ; 110da7f033dSHerbert Xu 111da7f033dSHerbert Xu len = p - name; 112da7f033dSHerbert Xu if (!len || *p != '(') 113da7f033dSHerbert Xu goto err_free_param; 114da7f033dSHerbert Xu 115da7f033dSHerbert Xu memcpy(param->template, name, len); 116da7f033dSHerbert Xu 117da7f033dSHerbert Xu i = 0; 118da7f033dSHerbert Xu for (;;) { 119da7f033dSHerbert Xu int notnum = 0; 120da7f033dSHerbert Xu 121da7f033dSHerbert Xu name = ++p; 122da7f033dSHerbert Xu len = 0; 123da7f033dSHerbert Xu 124da7f033dSHerbert Xu for (; isalnum(*p) || *p == '-' || *p == '_'; p++) 125da7f033dSHerbert Xu notnum |= !isdigit(*p); 126da7f033dSHerbert Xu 127da7f033dSHerbert Xu if (*p == '(') { 128da7f033dSHerbert Xu int recursion = 0; 129da7f033dSHerbert Xu 130da7f033dSHerbert Xu for (;;) { 131da7f033dSHerbert Xu if (!*++p) 132da7f033dSHerbert Xu goto err_free_param; 133da7f033dSHerbert Xu if (*p == '(') 134da7f033dSHerbert Xu recursion++; 135da7f033dSHerbert Xu else if (*p == ')' && !recursion--) 136da7f033dSHerbert Xu break; 137da7f033dSHerbert Xu } 138da7f033dSHerbert Xu 139da7f033dSHerbert Xu notnum = 1; 140da7f033dSHerbert Xu p++; 141da7f033dSHerbert Xu } 142da7f033dSHerbert Xu 143da7f033dSHerbert Xu len = p - name; 144da7f033dSHerbert Xu if (!len) 145da7f033dSHerbert Xu goto err_free_param; 146da7f033dSHerbert Xu 147da7f033dSHerbert Xu if (notnum) { 148da7f033dSHerbert Xu param->attrs[i].alg.attr.rta_len = 149da7f033dSHerbert Xu sizeof(param->attrs[i].alg); 150da7f033dSHerbert Xu param->attrs[i].alg.attr.rta_type = CRYPTOA_ALG; 151da7f033dSHerbert Xu memcpy(param->attrs[i].alg.data.name, name, len); 152da7f033dSHerbert Xu } else { 153da7f033dSHerbert Xu param->attrs[i].nu32.attr.rta_len = 154da7f033dSHerbert Xu sizeof(param->attrs[i].nu32); 155da7f033dSHerbert Xu param->attrs[i].nu32.attr.rta_type = CRYPTOA_U32; 156da7f033dSHerbert Xu param->attrs[i].nu32.data.num = 157da7f033dSHerbert Xu simple_strtol(name, NULL, 0); 158da7f033dSHerbert Xu } 159da7f033dSHerbert Xu 160da7f033dSHerbert Xu param->tb[i + 1] = ¶m->attrs[i].attr; 161da7f033dSHerbert Xu i++; 162da7f033dSHerbert Xu 163da7f033dSHerbert Xu if (i >= CRYPTO_MAX_ATTRS) 164da7f033dSHerbert Xu goto err_free_param; 165da7f033dSHerbert Xu 166da7f033dSHerbert Xu if (*p == ')') 167da7f033dSHerbert Xu break; 168da7f033dSHerbert Xu 169da7f033dSHerbert Xu if (*p != ',') 170da7f033dSHerbert Xu goto err_free_param; 171da7f033dSHerbert Xu } 172da7f033dSHerbert Xu 173da7f033dSHerbert Xu if (!i) 174da7f033dSHerbert Xu goto err_free_param; 175da7f033dSHerbert Xu 176da7f033dSHerbert Xu param->tb[i + 1] = NULL; 177da7f033dSHerbert Xu 178da7f033dSHerbert Xu param->type.attr.rta_len = sizeof(param->type); 179da7f033dSHerbert Xu param->type.attr.rta_type = CRYPTOA_TYPE; 18073d3864aSHerbert Xu param->type.data.type = larval->alg.cra_flags & ~CRYPTO_ALG_TESTED; 18173d3864aSHerbert Xu param->type.data.mask = larval->mask & ~CRYPTO_ALG_TESTED; 182da7f033dSHerbert Xu param->tb[0] = ¶m->type.attr; 183da7f033dSHerbert Xu 18473d3864aSHerbert Xu param->otype = larval->alg.cra_flags; 18573d3864aSHerbert Xu param->omask = larval->mask; 18673d3864aSHerbert Xu 187da7f033dSHerbert Xu memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); 188da7f033dSHerbert Xu 18973d3864aSHerbert Xu thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe"); 19073d3864aSHerbert Xu if (IS_ERR(thread)) 19173d3864aSHerbert Xu goto err_free_param; 19273d3864aSHerbert Xu 19373d3864aSHerbert Xu return NOTIFY_STOP; 19473d3864aSHerbert Xu 19573d3864aSHerbert Xu err_free_param: 19673d3864aSHerbert Xu kfree(param); 19773d3864aSHerbert Xu err_put_module: 19873d3864aSHerbert Xu module_put(THIS_MODULE); 19973d3864aSHerbert Xu err: 20073d3864aSHerbert Xu return NOTIFY_OK; 20173d3864aSHerbert Xu } 20273d3864aSHerbert Xu 20373d3864aSHerbert Xu static int cryptomgr_test(void *data) 20473d3864aSHerbert Xu { 20573d3864aSHerbert Xu struct crypto_test_param *param = data; 20673d3864aSHerbert Xu u32 type = param->type; 20773d3864aSHerbert Xu int err = 0; 20873d3864aSHerbert Xu 20973d3864aSHerbert Xu if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & 21073d3864aSHerbert Xu CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV)) 21173d3864aSHerbert Xu goto skiptest; 21273d3864aSHerbert Xu 2131aa4ecd9SHerbert Xu err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED); 21473d3864aSHerbert Xu 21573d3864aSHerbert Xu skiptest: 21673d3864aSHerbert Xu crypto_alg_tested(param->driver, err); 21773d3864aSHerbert Xu 21873d3864aSHerbert Xu kfree(param); 21973d3864aSHerbert Xu module_put_and_exit(0); 22073d3864aSHerbert Xu } 22173d3864aSHerbert Xu 22273d3864aSHerbert Xu static int cryptomgr_schedule_test(struct crypto_alg *alg) 22373d3864aSHerbert Xu { 22473d3864aSHerbert Xu struct task_struct *thread; 22573d3864aSHerbert Xu struct crypto_test_param *param; 22673d3864aSHerbert Xu 22773d3864aSHerbert Xu if (!try_module_get(THIS_MODULE)) 22873d3864aSHerbert Xu goto err; 22973d3864aSHerbert Xu 23073d3864aSHerbert Xu param = kzalloc(sizeof(*param), GFP_KERNEL); 23173d3864aSHerbert Xu if (!param) 23273d3864aSHerbert Xu goto err_put_module; 23373d3864aSHerbert Xu 23473d3864aSHerbert Xu memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver)); 23573d3864aSHerbert Xu memcpy(param->alg, alg->cra_name, sizeof(param->alg)); 23673d3864aSHerbert Xu param->type = alg->cra_flags; 23773d3864aSHerbert Xu 23873d3864aSHerbert Xu thread = kthread_run(cryptomgr_test, param, "cryptomgr_test"); 239da7f033dSHerbert Xu if (IS_ERR(thread)) 240da7f033dSHerbert Xu goto err_free_param; 241da7f033dSHerbert Xu 242da7f033dSHerbert Xu return NOTIFY_STOP; 243da7f033dSHerbert Xu 244da7f033dSHerbert Xu err_free_param: 245da7f033dSHerbert Xu kfree(param); 246da7f033dSHerbert Xu err_put_module: 247da7f033dSHerbert Xu module_put(THIS_MODULE); 248da7f033dSHerbert Xu err: 249da7f033dSHerbert Xu return NOTIFY_OK; 250da7f033dSHerbert Xu } 251da7f033dSHerbert Xu 252da7f033dSHerbert Xu static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, 253da7f033dSHerbert Xu void *data) 254da7f033dSHerbert Xu { 255da7f033dSHerbert Xu switch (msg) { 256da7f033dSHerbert Xu case CRYPTO_MSG_ALG_REQUEST: 257da7f033dSHerbert Xu return cryptomgr_schedule_probe(data); 25873d3864aSHerbert Xu case CRYPTO_MSG_ALG_REGISTER: 25973d3864aSHerbert Xu return cryptomgr_schedule_test(data); 260da7f033dSHerbert Xu } 261da7f033dSHerbert Xu 262da7f033dSHerbert Xu return NOTIFY_DONE; 263da7f033dSHerbert Xu } 264da7f033dSHerbert Xu 265da7f033dSHerbert Xu static struct notifier_block cryptomgr_notifier = { 266da7f033dSHerbert Xu .notifier_call = cryptomgr_notify, 267da7f033dSHerbert Xu }; 268da7f033dSHerbert Xu 269da7f033dSHerbert Xu static int __init cryptomgr_init(void) 270da7f033dSHerbert Xu { 271da7f033dSHerbert Xu int err; 272da7f033dSHerbert Xu 273da7f033dSHerbert Xu err = testmgr_init(); 274da7f033dSHerbert Xu if (err) 275da7f033dSHerbert Xu return err; 276da7f033dSHerbert Xu 277da7f033dSHerbert Xu err = crypto_register_notifier(&cryptomgr_notifier); 278da7f033dSHerbert Xu if (err) 279da7f033dSHerbert Xu goto free_testmgr; 280da7f033dSHerbert Xu 281da7f033dSHerbert Xu return 0; 282da7f033dSHerbert Xu 283da7f033dSHerbert Xu free_testmgr: 284da7f033dSHerbert Xu testmgr_exit(); 285da7f033dSHerbert Xu return err; 286da7f033dSHerbert Xu } 287da7f033dSHerbert Xu 288da7f033dSHerbert Xu static void __exit cryptomgr_exit(void) 289da7f033dSHerbert Xu { 290da7f033dSHerbert Xu int err = crypto_unregister_notifier(&cryptomgr_notifier); 291da7f033dSHerbert Xu BUG_ON(err); 292da7f033dSHerbert Xu 293da7f033dSHerbert Xu testmgr_exit(); 294da7f033dSHerbert Xu } 295da7f033dSHerbert Xu 296da7f033dSHerbert Xu subsys_initcall(cryptomgr_init); 297da7f033dSHerbert Xu module_exit(cryptomgr_exit); 298da7f033dSHerbert Xu 299da7f033dSHerbert Xu MODULE_LICENSE("GPL"); 300da7f033dSHerbert Xu MODULE_DESCRIPTION("Crypto Algorithm Manager"); 301