]> git.sesse.net Git - bcachefs-tools-debian/blob - linux/crypto/algapi.c
bcache in userspace; userspace fsck
[bcachefs-tools-debian] / linux / 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/byteorder.h>
14 #include <linux/err.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/list.h>
18 #include <linux/module.h>
19 #include <linux/printk.h>
20 #include <linux/rtnetlink.h>
21 #include <linux/slab.h>
22 #include <linux/string.h>
23
24 #include "internal.h"
25
26 static inline int crypto_set_driver_name(struct crypto_alg *alg)
27 {
28         static const char suffix[] = "-generic";
29         char *driver_name = alg->cra_driver_name;
30         int len;
31
32         if (*driver_name)
33                 return 0;
34
35         len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
36         if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
37                 return -ENAMETOOLONG;
38
39         memcpy(driver_name + len, suffix, sizeof(suffix));
40         return 0;
41 }
42
43 static int crypto_check_alg(struct crypto_alg *alg)
44 {
45         if (alg->cra_alignmask & (alg->cra_alignmask + 1))
46                 return -EINVAL;
47
48         if (alg->cra_blocksize > PAGE_SIZE / 8)
49                 return -EINVAL;
50
51         if (alg->cra_priority < 0)
52                 return -EINVAL;
53
54         atomic_set(&alg->cra_refcnt, 1);
55
56         return crypto_set_driver_name(alg);
57 }
58
59 static int __crypto_register_alg(struct crypto_alg *alg)
60 {
61         struct crypto_alg *q;
62         int ret = -EAGAIN;
63
64         INIT_LIST_HEAD(&alg->cra_users);
65
66         ret = -EEXIST;
67
68         list_for_each_entry(q, &crypto_alg_list, cra_list) {
69                 if (q == alg)
70                         goto err;
71
72                 if (!strcmp(q->cra_driver_name, alg->cra_name) ||
73                     !strcmp(q->cra_name, alg->cra_driver_name))
74                         goto err;
75         }
76
77         list_add(&alg->cra_list, &crypto_alg_list);
78         return 0;
79 err:
80         return ret;
81 }
82
83 void crypto_remove_final(struct list_head *list)
84 {
85         struct crypto_alg *alg;
86         struct crypto_alg *n;
87
88         list_for_each_entry_safe(alg, n, list, cra_list) {
89                 list_del_init(&alg->cra_list);
90                 crypto_alg_put(alg);
91         }
92 }
93
94 int crypto_register_alg(struct crypto_alg *alg)
95 {
96         int err;
97
98         err = crypto_check_alg(alg);
99         if (err)
100                 return err;
101
102         down_write(&crypto_alg_sem);
103         err = __crypto_register_alg(alg);
104         up_write(&crypto_alg_sem);
105
106         return err;
107 }
108
109 static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
110 {
111         if (unlikely(list_empty(&alg->cra_list)))
112                 return -ENOENT;
113
114         list_del_init(&alg->cra_list);
115         return 0;
116 }
117
118 int crypto_unregister_alg(struct crypto_alg *alg)
119 {
120         int ret;
121         LIST_HEAD(list);
122
123         down_write(&crypto_alg_sem);
124         ret = crypto_remove_alg(alg, &list);
125         up_write(&crypto_alg_sem);
126
127         if (ret)
128                 return ret;
129
130         BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
131         if (alg->cra_destroy)
132                 alg->cra_destroy(alg);
133
134         crypto_remove_final(&list);
135         return 0;
136 }
137
138 int crypto_register_algs(struct crypto_alg *algs, int count)
139 {
140         int i, ret;
141
142         for (i = 0; i < count; i++) {
143                 ret = crypto_register_alg(&algs[i]);
144                 if (ret)
145                         goto err;
146         }
147
148         return 0;
149
150 err:
151         for (--i; i >= 0; --i)
152                 crypto_unregister_alg(&algs[i]);
153
154         return ret;
155 }
156
157 int crypto_unregister_algs(struct crypto_alg *algs, int count)
158 {
159         int i, ret;
160
161         for (i = 0; i < count; i++) {
162                 ret = crypto_unregister_alg(&algs[i]);
163                 if (ret)
164                         pr_err("Failed to unregister %s %s: %d\n",
165                                algs[i].cra_driver_name, algs[i].cra_name, ret);
166         }
167
168         return 0;
169 }
170
171 struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
172 {
173         struct rtattr *rta = tb[0];
174         struct crypto_attr_type *algt;
175
176         if (!rta)
177                 return ERR_PTR(-ENOENT);
178         if (RTA_PAYLOAD(rta) < sizeof(*algt))
179                 return ERR_PTR(-EINVAL);
180         if (rta->rta_type != CRYPTOA_TYPE)
181                 return ERR_PTR(-EINVAL);
182
183         algt = RTA_DATA(rta);
184
185         return algt;
186 }
187
188 int crypto_check_attr_type(struct rtattr **tb, u32 type)
189 {
190         struct crypto_attr_type *algt;
191
192         algt = crypto_get_attr_type(tb);
193         if (IS_ERR(algt))
194                 return PTR_ERR(algt);
195
196         if ((algt->type ^ type) & algt->mask)
197                 return -EINVAL;
198
199         return 0;
200 }
201
202 const char *crypto_attr_alg_name(struct rtattr *rta)
203 {
204         struct crypto_attr_alg *alga;
205
206         if (!rta)
207                 return ERR_PTR(-ENOENT);
208         if (RTA_PAYLOAD(rta) < sizeof(*alga))
209                 return ERR_PTR(-EINVAL);
210         if (rta->rta_type != CRYPTOA_ALG)
211                 return ERR_PTR(-EINVAL);
212
213         alga = RTA_DATA(rta);
214         alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
215
216         return alga->name;
217 }
218
219 struct crypto_alg *crypto_attr_alg2(struct rtattr *rta,
220                                     const struct crypto_type *frontend,
221                                     u32 type, u32 mask)
222 {
223         const char *name;
224
225         name = crypto_attr_alg_name(rta);
226         if (IS_ERR(name))
227                 return ERR_CAST(name);
228
229         return crypto_find_alg(name, frontend, type, mask);
230 }
231
232 int crypto_attr_u32(struct rtattr *rta, u32 *num)
233 {
234         struct crypto_attr_u32 *nu32;
235
236         if (!rta)
237                 return -ENOENT;
238         if (RTA_PAYLOAD(rta) < sizeof(*nu32))
239                 return -EINVAL;
240         if (rta->rta_type != CRYPTOA_U32)
241                 return -EINVAL;
242
243         nu32 = RTA_DATA(rta);
244         *num = nu32->num;
245
246         return 0;
247 }
248
249 static inline void crypto_inc_byte(u8 *a, unsigned int size)
250 {
251         u8 *b = (a + size);
252         u8 c;
253
254         for (; size; size--) {
255                 c = *--b + 1;
256                 *b = c;
257                 if (c)
258                         break;
259         }
260 }
261
262 void crypto_inc(u8 *a, unsigned int size)
263 {
264         __be32 *b = (__be32 *)(a + size);
265         u32 c;
266
267         for (; size >= 4; size -= 4) {
268                 c = be32_to_cpu(*--b) + 1;
269                 *b = cpu_to_be32(c);
270                 if (c)
271                         return;
272         }
273
274         crypto_inc_byte(a, size);
275 }
276
277 static inline void crypto_xor_byte(u8 *a, const u8 *b, unsigned int size)
278 {
279         for (; size; size--)
280                 *a++ ^= *b++;
281 }
282
283 void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
284 {
285         u32 *a = (u32 *)dst;
286         u32 *b = (u32 *)src;
287
288         for (; size >= 4; size -= 4)
289                 *a++ ^= *b++;
290
291         crypto_xor_byte((u8 *)a, (u8 *)b, size);
292 }
293
294 unsigned int crypto_alg_extsize(struct crypto_alg *alg)
295 {
296         return alg->cra_ctxsize +
297                (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
298 }
299
300 int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
301                         u32 type, u32 mask)
302 {
303         int ret = 0;
304         struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask);
305
306         if (!IS_ERR(alg)) {
307                 crypto_alg_put(alg);
308                 ret = 1;
309         }
310
311         return ret;
312 }
313
314 MODULE_LICENSE("GPL");
315 MODULE_DESCRIPTION("Cryptographic algorithms API");