Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[sfrench/cifs-2.6.git] / fs / ceph / crypto.c
1
2 #include "ceph_debug.h"
3
4 #include <linux/err.h>
5 #include <linux/scatterlist.h>
6 #include <crypto/hash.h>
7
8 #include "crypto.h"
9 #include "decode.h"
10
11 int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
12 {
13         if (*p + sizeof(u16) + sizeof(key->created) +
14             sizeof(u16) + key->len > end)
15                 return -ERANGE;
16         ceph_encode_16(p, key->type);
17         ceph_encode_copy(p, &key->created, sizeof(key->created));
18         ceph_encode_16(p, key->len);
19         ceph_encode_copy(p, key->key, key->len);
20         return 0;
21 }
22
23 int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
24 {
25         ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad);
26         key->type = ceph_decode_16(p);
27         ceph_decode_copy(p, &key->created, sizeof(key->created));
28         key->len = ceph_decode_16(p);
29         ceph_decode_need(p, end, key->len, bad);
30         key->key = kmalloc(key->len, GFP_NOFS);
31         if (!key->key)
32                 return -ENOMEM;
33         ceph_decode_copy(p, key->key, key->len);
34         return 0;
35
36 bad:
37         dout("failed to decode crypto key\n");
38         return -EINVAL;
39 }
40
41 int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
42 {
43         int inlen = strlen(inkey);
44         int blen = inlen * 3 / 4;
45         void *buf, *p;
46         int ret;
47
48         dout("crypto_key_unarmor %s\n", inkey);
49         buf = kmalloc(blen, GFP_NOFS);
50         if (!buf)
51                 return -ENOMEM;
52         blen = ceph_unarmor(buf, inkey, inkey+inlen);
53         if (blen < 0) {
54                 kfree(buf);
55                 return blen;
56         }
57
58         p = buf;
59         ret = ceph_crypto_key_decode(key, &p, p + blen);
60         kfree(buf);
61         if (ret)
62                 return ret;
63         dout("crypto_key_unarmor key %p type %d len %d\n", key,
64              key->type, key->len);
65         return 0;
66 }
67
68
69
70 #define AES_KEY_SIZE 16
71
72 static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
73 {
74         return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
75 }
76
77 const u8 *aes_iv = "cephsageyudagreg";
78
79 int ceph_aes_encrypt(const void *key, int key_len, void *dst, size_t *dst_len,
80                      const void *src, size_t src_len)
81 {
82         struct scatterlist sg_in[2], sg_out[1];
83         struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
84         struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
85         int ret;
86         void *iv;
87         int ivsize;
88         size_t zero_padding = (0x10 - (src_len & 0x0f));
89         char pad[16];
90
91         if (IS_ERR(tfm))
92                 return PTR_ERR(tfm);
93
94         memset(pad, zero_padding, zero_padding);
95
96         *dst_len = src_len + zero_padding;
97
98         crypto_blkcipher_setkey((void *)tfm, key, key_len);
99         sg_init_table(sg_in, 2);
100         sg_set_buf(&sg_in[0], src, src_len);
101         sg_set_buf(&sg_in[1], pad, zero_padding);
102         sg_init_table(sg_out, 1);
103         sg_set_buf(sg_out, dst, *dst_len);
104         iv = crypto_blkcipher_crt(tfm)->iv;
105         ivsize = crypto_blkcipher_ivsize(tfm);
106
107         memcpy(iv, aes_iv, ivsize);
108         /*
109         print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
110                        key, key_len, 1);
111         print_hex_dump(KERN_ERR, "enc src: ", DUMP_PREFIX_NONE, 16, 1,
112                         src, src_len, 1);
113         print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
114                         pad, zero_padding, 1);
115         */
116         ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
117                                      src_len + zero_padding);
118         crypto_free_blkcipher(tfm);
119         if (ret < 0)
120                 pr_err("ceph_aes_crypt failed %d\n", ret);
121         /*
122         print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
123                        dst, *dst_len, 1);
124         */
125         return 0;
126 }
127
128 int ceph_aes_encrypt2(const void *key, int key_len, void *dst, size_t *dst_len,
129                       const void *src1, size_t src1_len,
130                       const void *src2, size_t src2_len)
131 {
132         struct scatterlist sg_in[3], sg_out[1];
133         struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
134         struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
135         int ret;
136         void *iv;
137         int ivsize;
138         size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f));
139         char pad[16];
140
141         if (IS_ERR(tfm))
142                 return PTR_ERR(tfm);
143
144         memset(pad, zero_padding, zero_padding);
145
146         *dst_len = src1_len + src2_len + zero_padding;
147
148         crypto_blkcipher_setkey((void *)tfm, key, key_len);
149         sg_init_table(sg_in, 3);
150         sg_set_buf(&sg_in[0], src1, src1_len);
151         sg_set_buf(&sg_in[1], src2, src2_len);
152         sg_set_buf(&sg_in[2], pad, zero_padding);
153         sg_init_table(sg_out, 1);
154         sg_set_buf(sg_out, dst, *dst_len);
155         iv = crypto_blkcipher_crt(tfm)->iv;
156         ivsize = crypto_blkcipher_ivsize(tfm);
157
158         memcpy(iv, aes_iv, ivsize);
159         /*
160         print_hex_dump(KERN_ERR, "enc  key: ", DUMP_PREFIX_NONE, 16, 1,
161                        key, key_len, 1);
162         print_hex_dump(KERN_ERR, "enc src1: ", DUMP_PREFIX_NONE, 16, 1,
163                         src1, src1_len, 1);
164         print_hex_dump(KERN_ERR, "enc src2: ", DUMP_PREFIX_NONE, 16, 1,
165                         src2, src2_len, 1);
166         print_hex_dump(KERN_ERR, "enc  pad: ", DUMP_PREFIX_NONE, 16, 1,
167                         pad, zero_padding, 1);
168         */
169         ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
170                                      src1_len + src2_len + zero_padding);
171         crypto_free_blkcipher(tfm);
172         if (ret < 0)
173                 pr_err("ceph_aes_crypt2 failed %d\n", ret);
174         /*
175         print_hex_dump(KERN_ERR, "enc  out: ", DUMP_PREFIX_NONE, 16, 1,
176                        dst, *dst_len, 1);
177         */
178         return 0;
179 }
180
181 int ceph_aes_decrypt(const void *key, int key_len, void *dst, size_t *dst_len,
182                      const void *src, size_t src_len)
183 {
184         struct scatterlist sg_in[1], sg_out[2];
185         struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
186         struct blkcipher_desc desc = { .tfm = tfm };
187         char pad[16];
188         void *iv;
189         int ivsize;
190         int ret;
191         int last_byte;
192
193         if (IS_ERR(tfm))
194                 return PTR_ERR(tfm);
195
196         crypto_blkcipher_setkey((void *)tfm, key, key_len);
197         sg_init_table(sg_in, 1);
198         sg_init_table(sg_out, 2);
199         sg_set_buf(sg_in, src, src_len);
200         sg_set_buf(&sg_out[0], dst, *dst_len);
201         sg_set_buf(&sg_out[1], pad, sizeof(pad));
202
203         iv = crypto_blkcipher_crt(tfm)->iv;
204         ivsize = crypto_blkcipher_ivsize(tfm);
205
206         memcpy(iv, aes_iv, ivsize);
207
208         /*
209         print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1,
210                        key, key_len, 1);
211         print_hex_dump(KERN_ERR, "dec  in: ", DUMP_PREFIX_NONE, 16, 1,
212                        src, src_len, 1);
213         */
214
215         ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
216         crypto_free_blkcipher(tfm);
217         if (ret < 0) {
218                 pr_err("ceph_aes_decrypt failed %d\n", ret);
219                 return ret;
220         }
221
222         if (src_len <= *dst_len)
223                 last_byte = ((char *)dst)[src_len - 1];
224         else
225                 last_byte = pad[src_len - *dst_len - 1];
226         if (last_byte <= 16 && src_len >= last_byte) {
227                 *dst_len = src_len - last_byte;
228         } else {
229                 pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
230                        last_byte, (int)src_len);
231                 return -EPERM;  /* bad padding */
232         }
233         /*
234         print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
235                        dst, *dst_len, 1);
236         */
237         return 0;
238 }
239
240 int ceph_aes_decrypt2(const void *key, int key_len,
241                       void *dst1, size_t *dst1_len,
242                       void *dst2, size_t *dst2_len,
243                       const void *src, size_t src_len)
244 {
245         struct scatterlist sg_in[1], sg_out[3];
246         struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
247         struct blkcipher_desc desc = { .tfm = tfm };
248         char pad[16];
249         void *iv;
250         int ivsize;
251         int ret;
252         int last_byte;
253
254         if (IS_ERR(tfm))
255                 return PTR_ERR(tfm);
256
257         sg_init_table(sg_in, 1);
258         sg_set_buf(sg_in, src, src_len);
259         sg_init_table(sg_out, 3);
260         sg_set_buf(&sg_out[0], dst1, *dst1_len);
261         sg_set_buf(&sg_out[1], dst2, *dst2_len);
262         sg_set_buf(&sg_out[2], pad, sizeof(pad));
263
264         crypto_blkcipher_setkey((void *)tfm, key, key_len);
265         iv = crypto_blkcipher_crt(tfm)->iv;
266         ivsize = crypto_blkcipher_ivsize(tfm);
267
268         memcpy(iv, aes_iv, ivsize);
269
270         /*
271         print_hex_dump(KERN_ERR, "dec  key: ", DUMP_PREFIX_NONE, 16, 1,
272                        key, key_len, 1);
273         print_hex_dump(KERN_ERR, "dec   in: ", DUMP_PREFIX_NONE, 16, 1,
274                        src, src_len, 1);
275         */
276
277         ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
278         crypto_free_blkcipher(tfm);
279         if (ret < 0) {
280                 pr_err("ceph_aes_decrypt failed %d\n", ret);
281                 return ret;
282         }
283
284         if (src_len <= *dst1_len)
285                 last_byte = ((char *)dst1)[src_len - 1];
286         else if (src_len <= *dst1_len + *dst2_len)
287                 last_byte = ((char *)dst2)[src_len - *dst1_len - 1];
288         else
289                 last_byte = pad[src_len - *dst1_len - *dst2_len - 1];
290         if (last_byte <= 16 && src_len >= last_byte) {
291                 src_len -= last_byte;
292         } else {
293                 pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
294                        last_byte, (int)src_len);
295                 return -EPERM;  /* bad padding */
296         }
297
298         if (src_len < *dst1_len) {
299                 *dst1_len = src_len;
300                 *dst2_len = 0;
301         } else {
302                 *dst2_len = src_len - *dst1_len;
303         }
304         /*
305         print_hex_dump(KERN_ERR, "dec  out1: ", DUMP_PREFIX_NONE, 16, 1,
306                        dst1, *dst1_len, 1);
307         print_hex_dump(KERN_ERR, "dec  out2: ", DUMP_PREFIX_NONE, 16, 1,
308                        dst2, *dst2_len, 1);
309         */
310
311         return 0;
312 }
313
314
315 int ceph_decrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
316                  const void *src, size_t src_len)
317 {
318         switch (secret->type) {
319         case CEPH_CRYPTO_NONE:
320                 if (*dst_len < src_len)
321                         return -ERANGE;
322                 memcpy(dst, src, src_len);
323                 *dst_len = src_len;
324                 return 0;
325
326         case CEPH_CRYPTO_AES:
327                 return ceph_aes_decrypt(secret->key, secret->len, dst,
328                                         dst_len, src, src_len);
329
330         default:
331                 return -EINVAL;
332         }
333 }
334
335 int ceph_decrypt2(struct ceph_crypto_key *secret,
336                         void *dst1, size_t *dst1_len,
337                         void *dst2, size_t *dst2_len,
338                         const void *src, size_t src_len)
339 {
340         size_t t;
341
342         switch (secret->type) {
343         case CEPH_CRYPTO_NONE:
344                 if (*dst1_len + *dst2_len < src_len)
345                         return -ERANGE;
346                 t = min(*dst1_len, src_len);
347                 memcpy(dst1, src, t);
348                 *dst1_len = t;
349                 src += t;
350                 src_len -= t;
351                 if (src_len) {
352                         t = min(*dst2_len, src_len);
353                         memcpy(dst2, src, t);
354                         *dst2_len = t;
355                 }
356                 return 0;
357
358         case CEPH_CRYPTO_AES:
359                 return ceph_aes_decrypt2(secret->key, secret->len,
360                                          dst1, dst1_len, dst2, dst2_len,
361                                          src, src_len);
362
363         default:
364                 return -EINVAL;
365         }
366 }
367
368 int ceph_encrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
369                  const void *src, size_t src_len)
370 {
371         switch (secret->type) {
372         case CEPH_CRYPTO_NONE:
373                 if (*dst_len < src_len)
374                         return -ERANGE;
375                 memcpy(dst, src, src_len);
376                 *dst_len = src_len;
377                 return 0;
378
379         case CEPH_CRYPTO_AES:
380                 return ceph_aes_encrypt(secret->key, secret->len, dst,
381                                         dst_len, src, src_len);
382
383         default:
384                 return -EINVAL;
385         }
386 }
387
388 int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
389                   const void *src1, size_t src1_len,
390                   const void *src2, size_t src2_len)
391 {
392         switch (secret->type) {
393         case CEPH_CRYPTO_NONE:
394                 if (*dst_len < src1_len + src2_len)
395                         return -ERANGE;
396                 memcpy(dst, src1, src1_len);
397                 memcpy(dst + src1_len, src2, src2_len);
398                 *dst_len = src1_len + src2_len;
399                 return 0;
400
401         case CEPH_CRYPTO_AES:
402                 return ceph_aes_encrypt2(secret->key, secret->len, dst, dst_len,
403                                          src1, src1_len, src2, src2_len);
404
405         default:
406                 return -EINVAL;
407         }
408 }