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