[CRYPTO] api: Split out low-level API
[linux-flexiantxendom0-natty.git] / crypto / algapi.c
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)
9  * any later version.
10  *
11  */
12
13 #include <linux/errno.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/string.h>
18
19 #include "internal.h"
20
21 static inline int crypto_set_driver_name(struct crypto_alg *alg)
22 {
23         static const char suffix[] = "-generic";
24         char *driver_name = alg->cra_driver_name;
25         int len;
26
27         if (*driver_name)
28                 return 0;
29
30         len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
31         if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
32                 return -ENAMETOOLONG;
33
34         memcpy(driver_name + len, suffix, sizeof(suffix));
35         return 0;
36 }
37
38 int crypto_register_alg(struct crypto_alg *alg)
39 {
40         int ret;
41         struct crypto_alg *q;
42
43         if (alg->cra_alignmask & (alg->cra_alignmask + 1))
44                 return -EINVAL;
45
46         if (alg->cra_alignmask & alg->cra_blocksize)
47                 return -EINVAL;
48
49         if (alg->cra_blocksize > PAGE_SIZE / 8)
50                 return -EINVAL;
51
52         if (alg->cra_priority < 0)
53                 return -EINVAL;
54         
55         ret = crypto_set_driver_name(alg);
56         if (unlikely(ret))
57                 return ret;
58
59         down_write(&crypto_alg_sem);
60         
61         list_for_each_entry(q, &crypto_alg_list, cra_list) {
62                 if (q == alg) {
63                         ret = -EEXIST;
64                         goto out;
65                 }
66         }
67         
68         list_add(&alg->cra_list, &crypto_alg_list);
69         atomic_set(&alg->cra_refcnt, 1);
70 out:    
71         up_write(&crypto_alg_sem);
72         return ret;
73 }
74 EXPORT_SYMBOL_GPL(crypto_register_alg);
75
76 int crypto_unregister_alg(struct crypto_alg *alg)
77 {
78         int ret = -ENOENT;
79         struct crypto_alg *q;
80         
81         down_write(&crypto_alg_sem);
82         list_for_each_entry(q, &crypto_alg_list, cra_list) {
83                 if (alg == q) {
84                         list_del(&alg->cra_list);
85                         ret = 0;
86                         goto out;
87                 }
88         }
89 out:    
90         up_write(&crypto_alg_sem);
91
92         if (ret)
93                 return ret;
94
95         BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
96         if (alg->cra_destroy)
97                 alg->cra_destroy(alg);
98
99         return 0;
100 }
101 EXPORT_SYMBOL_GPL(crypto_unregister_alg);
102
103 static int __init crypto_algapi_init(void)
104 {
105         crypto_init_proc();
106         return 0;
107 }
108
109 static void __exit crypto_algapi_exit(void)
110 {
111         crypto_exit_proc();
112 }
113
114 module_init(crypto_algapi_init);
115 module_exit(crypto_algapi_exit);
116
117 MODULE_LICENSE("GPL");
118 MODULE_DESCRIPTION("Cryptographic algorithms API");