at v2.6.21 157 lines 3.3 kB view raw
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/module.h> 18#include <linux/notifier.h> 19#include <linux/rtnetlink.h> 20#include <linux/sched.h> 21#include <linux/string.h> 22#include <linux/workqueue.h> 23 24#include "internal.h" 25 26struct cryptomgr_param { 27 struct work_struct work; 28 29 struct { 30 struct rtattr attr; 31 struct crypto_attr_alg data; 32 } alg; 33 34 struct { 35 u32 type; 36 u32 mask; 37 char name[CRYPTO_MAX_ALG_NAME]; 38 } larval; 39 40 char template[CRYPTO_MAX_ALG_NAME]; 41}; 42 43static void cryptomgr_probe(struct work_struct *work) 44{ 45 struct cryptomgr_param *param = 46 container_of(work, struct cryptomgr_param, work); 47 struct crypto_template *tmpl; 48 struct crypto_instance *inst; 49 int err; 50 51 tmpl = crypto_lookup_template(param->template); 52 if (!tmpl) 53 goto err; 54 55 do { 56 inst = tmpl->alloc(&param->alg, sizeof(param->alg)); 57 if (IS_ERR(inst)) 58 err = PTR_ERR(inst); 59 else if ((err = crypto_register_instance(tmpl, inst))) 60 tmpl->free(inst); 61 } while (err == -EAGAIN && !signal_pending(current)); 62 63 crypto_tmpl_put(tmpl); 64 65 if (err) 66 goto err; 67 68out: 69 kfree(param); 70 return; 71 72err: 73 crypto_larval_error(param->larval.name, param->larval.type, 74 param->larval.mask); 75 goto out; 76} 77 78static int cryptomgr_schedule_probe(struct crypto_larval *larval) 79{ 80 struct cryptomgr_param *param; 81 const char *name = larval->alg.cra_name; 82 const char *p; 83 unsigned int len; 84 85 param = kmalloc(sizeof(*param), GFP_KERNEL); 86 if (!param) 87 goto err; 88 89 for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) 90 ; 91 92 len = p - name; 93 if (!len || *p != '(') 94 goto err_free_param; 95 96 memcpy(param->template, name, len); 97 param->template[len] = 0; 98 99 name = p + 1; 100 for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) 101 ; 102 103 len = p - name; 104 if (!len || *p != ')' || p[1]) 105 goto err_free_param; 106 107 param->alg.attr.rta_len = sizeof(param->alg); 108 param->alg.attr.rta_type = CRYPTOA_ALG; 109 memcpy(param->alg.data.name, name, len); 110 param->alg.data.name[len] = 0; 111 112 memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); 113 param->larval.type = larval->alg.cra_flags; 114 param->larval.mask = larval->mask; 115 116 INIT_WORK(&param->work, cryptomgr_probe); 117 schedule_work(&param->work); 118 119 return NOTIFY_STOP; 120 121err_free_param: 122 kfree(param); 123err: 124 return NOTIFY_OK; 125} 126 127static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, 128 void *data) 129{ 130 switch (msg) { 131 case CRYPTO_MSG_ALG_REQUEST: 132 return cryptomgr_schedule_probe(data); 133 } 134 135 return NOTIFY_DONE; 136} 137 138static struct notifier_block cryptomgr_notifier = { 139 .notifier_call = cryptomgr_notify, 140}; 141 142static int __init cryptomgr_init(void) 143{ 144 return crypto_register_notifier(&cryptomgr_notifier); 145} 146 147static void __exit cryptomgr_exit(void) 148{ 149 int err = crypto_unregister_notifier(&cryptomgr_notifier); 150 BUG_ON(err); 151} 152 153module_init(cryptomgr_init); 154module_exit(cryptomgr_exit); 155 156MODULE_LICENSE("GPL"); 157MODULE_DESCRIPTION("Crypto Algorithm Manager");