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