1/* 2 * Create default crypto algorithm instances. 3 * 4 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 * 11 */ 12 13#include <linux/crypto.h> 14#include <linux/ctype.h> 15#include <linux/err.h> 16#include <linux/init.h> 17#include <linux/kthread.h> 18#include <linux/module.h> 19#include <linux/notifier.h> 20#include <linux/rtnetlink.h> 21#include <linux/sched.h> 22#include <linux/string.h> 23 24#include "internal.h" 25 26struct cryptomgr_param { 27 struct rtattr *tb[CRYPTOA_MAX]; 28 29 struct { 30 struct rtattr attr; 31 struct crypto_attr_type data; 32 } type; 33 34 struct { 35 struct rtattr attr; 36 struct crypto_attr_alg data; 37 } alg; 38 39 struct { 40 char name[CRYPTO_MAX_ALG_NAME]; 41 } larval; 42 43 char template[CRYPTO_MAX_ALG_NAME]; 44}; 45 46static int cryptomgr_probe(void *data) 47{ 48 struct cryptomgr_param *param = data; 49 struct crypto_template *tmpl; 50 struct crypto_instance *inst; 51 int err; 52 53 tmpl = crypto_lookup_template(param->template); 54 if (!tmpl) 55 goto err; 56 57 do { 58 inst = tmpl->alloc(param->tb); 59 if (IS_ERR(inst)) 60 err = PTR_ERR(inst); 61 else if ((err = crypto_register_instance(tmpl, inst))) 62 tmpl->free(inst); 63 } while (err == -EAGAIN && !signal_pending(current)); 64 65 crypto_tmpl_put(tmpl); 66 67 if (err) 68 goto err; 69 70out: 71 kfree(param); 72 module_put_and_exit(0); 73 74err: 75 crypto_larval_error(param->larval.name, param->type.data.type, 76 param->type.data.mask); 77 goto out; 78} 79 80static int cryptomgr_schedule_probe(struct crypto_larval *larval) 81{ 82 struct task_struct *thread; 83 struct cryptomgr_param *param; 84 const char *name = larval->alg.cra_name; 85 const char *p; 86 unsigned int len; 87 88 if (!try_module_get(THIS_MODULE)) 89 goto err; 90 91 param = kzalloc(sizeof(*param), GFP_KERNEL); 92 if (!param) 93 goto err_put_module; 94 95 for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) 96 ; 97 98 len = p - name; 99 if (!len || *p != '(') 100 goto err_free_param; 101 102 memcpy(param->template, name, len); 103 104 name = p + 1; 105 len = 0; 106 for (p = name; *p; p++) { 107 for (; isalnum(*p) || *p == '-' || *p == '_' || *p == '('; p++) 108 ; 109 110 if (*p != ')') 111 goto err_free_param; 112 113 len = p - name; 114 } 115 116 if (!len || name[len + 1]) 117 goto err_free_param; 118 119 param->type.attr.rta_len = sizeof(param->type); 120 param->type.attr.rta_type = CRYPTOA_TYPE; 121 param->type.data.type = larval->alg.cra_flags; 122 param->type.data.mask = larval->mask; 123 param->tb[CRYPTOA_TYPE - 1] = ¶m->type.attr; 124 125 param->alg.attr.rta_len = sizeof(param->alg); 126 param->alg.attr.rta_type = CRYPTOA_ALG; 127 memcpy(param->alg.data.name, name, len); 128 param->tb[CRYPTOA_ALG - 1] = ¶m->alg.attr; 129 130 memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); 131 132 thread = kthread_run(cryptomgr_probe, param, "cryptomgr"); 133 if (IS_ERR(thread)) 134 goto err_free_param; 135 136 return NOTIFY_STOP; 137 138err_free_param: 139 kfree(param); 140err_put_module: 141 module_put(THIS_MODULE); 142err: 143 return NOTIFY_OK; 144} 145 146static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, 147 void *data) 148{ 149 switch (msg) { 150 case CRYPTO_MSG_ALG_REQUEST: 151 return cryptomgr_schedule_probe(data); 152 } 153 154 return NOTIFY_DONE; 155} 156 157static struct notifier_block cryptomgr_notifier = { 158 .notifier_call = cryptomgr_notify, 159}; 160 161static int __init cryptomgr_init(void) 162{ 163 return crypto_register_notifier(&cryptomgr_notifier); 164} 165 166static void __exit cryptomgr_exit(void) 167{ 168 int err = crypto_unregister_notifier(&cryptomgr_notifier); 169 BUG_ON(err); 170} 171 172module_init(cryptomgr_init); 173module_exit(cryptomgr_exit); 174 175MODULE_LICENSE("GPL"); 176MODULE_DESCRIPTION("Crypto Algorithm Manager"); 177