algapi.c (c51b6c8102a82239163c8c04e404c7cc2857b4be) | algapi.c (73d3864a4823abda19ebc4387b6ddcbf416e3a77) |
---|---|
1/* 2 * Cryptographic API for algorithms (i.e., low-level API). 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) --- 7 unchanged lines hidden (view full) --- 16#include <linux/kernel.h> 17#include <linux/list.h> 18#include <linux/module.h> 19#include <linux/rtnetlink.h> 20#include <linux/string.h> 21 22#include "internal.h" 23 | 1/* 2 * Cryptographic API for algorithms (i.e., low-level API). 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) --- 7 unchanged lines hidden (view full) --- 16#include <linux/kernel.h> 17#include <linux/list.h> 18#include <linux/module.h> 19#include <linux/rtnetlink.h> 20#include <linux/string.h> 21 22#include "internal.h" 23 |
24static void crypto_remove_final(struct list_head *list); 25 |
|
24static LIST_HEAD(crypto_template_list); 25 26void crypto_larval_error(const char *name, u32 type, u32 mask) 27{ 28 struct crypto_alg *alg; 29 30 alg = crypto_alg_lookup(name, type, mask); 31 --- 89 unchanged lines hidden (view full) --- 121 } 122 123 while (!list_empty(&secondary_spawns)) { 124 list_for_each_entry_safe(spawn, n, &secondary_spawns, list) 125 crypto_remove_spawn(spawn, list, &secondary_spawns); 126 } 127} 128 | 26static LIST_HEAD(crypto_template_list); 27 28void crypto_larval_error(const char *name, u32 type, u32 mask) 29{ 30 struct crypto_alg *alg; 31 32 alg = crypto_alg_lookup(name, type, mask); 33 --- 89 unchanged lines hidden (view full) --- 123 } 124 125 while (!list_empty(&secondary_spawns)) { 126 list_for_each_entry_safe(spawn, n, &secondary_spawns, list) 127 crypto_remove_spawn(spawn, list, &secondary_spawns); 128 } 129} 130 |
129static int __crypto_register_alg(struct crypto_alg *alg, 130 struct list_head *list) | 131static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg) |
131{ 132 struct crypto_alg *q; | 132{ 133 struct crypto_alg *q; |
134 struct crypto_larval *larval; |
|
133 int ret = -EAGAIN; 134 135 if (crypto_is_dead(alg)) | 135 int ret = -EAGAIN; 136 137 if (crypto_is_dead(alg)) |
136 goto out; | 138 goto err; |
137 138 INIT_LIST_HEAD(&alg->cra_users); 139 | 139 140 INIT_LIST_HEAD(&alg->cra_users); 141 |
142 /* No cheating! */ 143 alg->cra_flags &= ~CRYPTO_ALG_TESTED; 144 |
|
140 ret = -EEXIST; 141 142 atomic_set(&alg->cra_refcnt, 1); 143 list_for_each_entry(q, &crypto_alg_list, cra_list) { 144 if (q == alg) | 145 ret = -EEXIST; 146 147 atomic_set(&alg->cra_refcnt, 1); 148 list_for_each_entry(q, &crypto_alg_list, cra_list) { 149 if (q == alg) |
145 goto out; | 150 goto err; |
146 | 151 |
152 if (crypto_is_larval(q)) { 153 if (!strcmp(alg->cra_driver_name, q->cra_driver_name)) 154 goto err; 155 continue; 156 } 157 158 if (!strcmp(q->cra_driver_name, alg->cra_name) || 159 !strcmp(q->cra_name, alg->cra_driver_name)) 160 goto err; 161 } 162 163 larval = crypto_larval_alloc(alg->cra_name, 164 alg->cra_flags | CRYPTO_ALG_TESTED, 0); 165 if (IS_ERR(larval)) 166 goto out; 167 168 ret = -ENOENT; 169 larval->adult = crypto_mod_get(alg); 170 if (!larval->adult) 171 goto free_larval; 172 173 atomic_set(&larval->alg.cra_refcnt, 1); 174 memcpy(larval->alg.cra_driver_name, alg->cra_driver_name, 175 CRYPTO_MAX_ALG_NAME); 176 larval->alg.cra_priority = alg->cra_priority; 177 178 list_add(&alg->cra_list, &crypto_alg_list); 179 list_add(&larval->alg.cra_list, &crypto_alg_list); 180 181out: 182 return larval; 183 184free_larval: 185 kfree(larval); 186err: 187 larval = ERR_PTR(ret); 188 goto out; 189} 190 191void crypto_alg_tested(const char *name, int err) 192{ 193 struct crypto_larval *test; 194 struct crypto_alg *alg; 195 struct crypto_alg *q; 196 LIST_HEAD(list); 197 198 down_write(&crypto_alg_sem); 199 list_for_each_entry(q, &crypto_alg_list, cra_list) { 200 if (!crypto_is_larval(q)) 201 continue; 202 203 test = (struct crypto_larval *)q; 204 205 if (!strcmp(q->cra_driver_name, name)) 206 goto found; 207 } 208 209 printk(KERN_ERR "alg: Unexpected test result for %s: %d\n", name, err); 210 goto unlock; 211 212found: 213 alg = test->adult; 214 if (err || list_empty(&alg->cra_list)) 215 goto complete; 216 217 alg->cra_flags |= CRYPTO_ALG_TESTED; 218 219 list_for_each_entry(q, &crypto_alg_list, cra_list) { 220 if (q == alg) 221 continue; 222 |
|
147 if (crypto_is_moribund(q)) 148 continue; 149 150 if (crypto_is_larval(q)) { 151 struct crypto_larval *larval = (void *)q; 152 153 /* 154 * Check to see if either our generic name or --- 18 unchanged lines hidden (view full) --- 173 174 if (strcmp(alg->cra_name, q->cra_name)) 175 continue; 176 177 if (strcmp(alg->cra_driver_name, q->cra_driver_name) && 178 q->cra_priority > alg->cra_priority) 179 continue; 180 | 223 if (crypto_is_moribund(q)) 224 continue; 225 226 if (crypto_is_larval(q)) { 227 struct crypto_larval *larval = (void *)q; 228 229 /* 230 * Check to see if either our generic name or --- 18 unchanged lines hidden (view full) --- 249 250 if (strcmp(alg->cra_name, q->cra_name)) 251 continue; 252 253 if (strcmp(alg->cra_driver_name, q->cra_driver_name) && 254 q->cra_priority > alg->cra_priority) 255 continue; 256 |
181 crypto_remove_spawns(&q->cra_users, list, alg->cra_flags); | 257 crypto_remove_spawns(&q->cra_users, &list, alg->cra_flags); |
182 } | 258 } |
183 184 list_add(&alg->cra_list, &crypto_alg_list); | |
185 | 259 |
186 crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg); 187 ret = 0; | 260complete: 261 complete_all(&test->completion); |
188 | 262 |
189out: 190 return ret; | 263unlock: 264 up_write(&crypto_alg_sem); 265 266 crypto_remove_final(&list); |
191} | 267} |
268EXPORT_SYMBOL_GPL(crypto_alg_tested); |
|
192 193static void crypto_remove_final(struct list_head *list) 194{ 195 struct crypto_alg *alg; 196 struct crypto_alg *n; 197 198 list_for_each_entry_safe(alg, n, list, cra_list) { 199 list_del_init(&alg->cra_list); 200 crypto_alg_put(alg); 201 } 202} 203 | 269 270static void crypto_remove_final(struct list_head *list) 271{ 272 struct crypto_alg *alg; 273 struct crypto_alg *n; 274 275 list_for_each_entry_safe(alg, n, list, cra_list) { 276 list_del_init(&alg->cra_list); 277 crypto_alg_put(alg); 278 } 279} 280 |
281static void crypto_wait_for_test(struct crypto_larval *larval) 282{ 283 int err; 284 285 err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult); 286 if (err != NOTIFY_STOP) { 287 if (WARN_ON(err != NOTIFY_DONE)) 288 goto out; 289 crypto_alg_tested(larval->alg.cra_driver_name, 0); 290 } 291 292 err = wait_for_completion_interruptible(&larval->completion); 293 WARN_ON(err); 294 295out: 296 crypto_larval_kill(&larval->alg); 297} 298 |
|
204int crypto_register_alg(struct crypto_alg *alg) 205{ | 299int crypto_register_alg(struct crypto_alg *alg) 300{ |
206 LIST_HEAD(list); | 301 struct crypto_larval *larval; |
207 int err; 208 209 err = crypto_check_alg(alg); 210 if (err) 211 return err; 212 213 down_write(&crypto_alg_sem); | 302 int err; 303 304 err = crypto_check_alg(alg); 305 if (err) 306 return err; 307 308 down_write(&crypto_alg_sem); |
214 err = __crypto_register_alg(alg, &list); | 309 larval = __crypto_register_alg(alg); |
215 up_write(&crypto_alg_sem); 216 | 310 up_write(&crypto_alg_sem); 311 |
217 crypto_remove_final(&list); 218 return err; | 312 if (IS_ERR(larval)) 313 return PTR_ERR(larval); 314 315 crypto_wait_for_test(larval); 316 return 0; |
219} 220EXPORT_SYMBOL_GPL(crypto_register_alg); 221 222static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) 223{ 224 if (unlikely(list_empty(&alg->cra_list))) 225 return -ENOENT; 226 --- 101 unchanged lines hidden (view full) --- 328{ 329 return try_then_request_module(__crypto_lookup_template(name), name); 330} 331EXPORT_SYMBOL_GPL(crypto_lookup_template); 332 333int crypto_register_instance(struct crypto_template *tmpl, 334 struct crypto_instance *inst) 335{ | 317} 318EXPORT_SYMBOL_GPL(crypto_register_alg); 319 320static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) 321{ 322 if (unlikely(list_empty(&alg->cra_list))) 323 return -ENOENT; 324 --- 101 unchanged lines hidden (view full) --- 426{ 427 return try_then_request_module(__crypto_lookup_template(name), name); 428} 429EXPORT_SYMBOL_GPL(crypto_lookup_template); 430 431int crypto_register_instance(struct crypto_template *tmpl, 432 struct crypto_instance *inst) 433{ |
336 LIST_HEAD(list); 337 int err = -EINVAL; | 434 struct crypto_larval *larval; 435 int err; |
338 339 err = crypto_check_alg(&inst->alg); 340 if (err) 341 goto err; 342 343 inst->alg.cra_module = tmpl->module; 344 345 down_write(&crypto_alg_sem); 346 | 436 437 err = crypto_check_alg(&inst->alg); 438 if (err) 439 goto err; 440 441 inst->alg.cra_module = tmpl->module; 442 443 down_write(&crypto_alg_sem); 444 |
347 err = __crypto_register_alg(&inst->alg, &list); 348 if (err) | 445 larval = __crypto_register_alg(&inst->alg); 446 if (IS_ERR(larval)) |
349 goto unlock; 350 351 hlist_add_head(&inst->list, &tmpl->instances); 352 inst->tmpl = tmpl; 353 354unlock: 355 up_write(&crypto_alg_sem); 356 | 447 goto unlock; 448 449 hlist_add_head(&inst->list, &tmpl->instances); 450 inst->tmpl = tmpl; 451 452unlock: 453 up_write(&crypto_alg_sem); 454 |
357 crypto_remove_final(&list); | 455 err = PTR_ERR(larval); 456 if (IS_ERR(larval)) 457 goto err; |
358 | 458 |
459 crypto_wait_for_test(larval); 460 err = 0; 461 |
|
359err: 360 return err; 361} 362EXPORT_SYMBOL_GPL(crypto_register_instance); 363 364int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, 365 struct crypto_instance *inst, u32 mask) 366{ --- 316 unchanged lines hidden --- | 462err: 463 return err; 464} 465EXPORT_SYMBOL_GPL(crypto_register_instance); 466 467int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, 468 struct crypto_instance *inst, u32 mask) 469{ --- 316 unchanged lines hidden --- |