[CRYPTO] api: Split out low-level API
[linux-block.git] / crypto / algapi.c
CommitLineData
cce9e06d
HX
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
21static 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
38int 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);
70out:
71 up_write(&crypto_alg_sem);
72 return ret;
73}
74EXPORT_SYMBOL_GPL(crypto_register_alg);
75
76int 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 }
89out:
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}
101EXPORT_SYMBOL_GPL(crypto_unregister_alg);
102
103static int __init crypto_algapi_init(void)
104{
105 crypto_init_proc();
106 return 0;
107}
108
109static void __exit crypto_algapi_exit(void)
110{
111 crypto_exit_proc();
112}
113
114module_init(crypto_algapi_init);
115module_exit(crypto_algapi_exit);
116
117MODULE_LICENSE("GPL");
118MODULE_DESCRIPTION("Cryptographic algorithms API");