Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/ceph/ceph_debug.h>
  4
  5#include <linux/err.h>
  6#include <linux/scatterlist.h>
  7#include <linux/sched.h>
  8#include <linux/slab.h>
  9#include <crypto/aes.h>
 10#include <crypto/skcipher.h>
 11#include <linux/key-type.h>
 12#include <linux/sched/mm.h>
 13
 14#include <keys/ceph-type.h>
 15#include <keys/user-type.h>
 16#include <linux/ceph/decode.h>
 17#include "crypto.h"
 18
 19/*
 20 * Set ->key and ->tfm.  The rest of the key should be filled in before
 21 * this function is called.
 22 */
 23static int set_secret(struct ceph_crypto_key *key, void *buf)
 24{
 25	unsigned int noio_flag;
 26	int ret;
 27
 28	key->key = NULL;
 29	key->tfm = NULL;
 30
 31	switch (key->type) {
 32	case CEPH_CRYPTO_NONE:
 33		return 0; /* nothing to do */
 34	case CEPH_CRYPTO_AES:
 35		break;
 36	default:
 37		return -ENOTSUPP;
 38	}
 39
 40	if (!key->len)
 41		return -EINVAL;
 42
 43	key->key = kmemdup(buf, key->len, GFP_NOIO);
 44	if (!key->key) {
 45		ret = -ENOMEM;
 46		goto fail;
 47	}
 48
 49	/* crypto_alloc_sync_skcipher() allocates with GFP_KERNEL */
 50	noio_flag = memalloc_noio_save();
 51	key->tfm = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0);
 52	memalloc_noio_restore(noio_flag);
 53	if (IS_ERR(key->tfm)) {
 54		ret = PTR_ERR(key->tfm);
 55		key->tfm = NULL;
 56		goto fail;
 57	}
 58
 59	ret = crypto_sync_skcipher_setkey(key->tfm, key->key, key->len);
 60	if (ret)
 61		goto fail;
 62
 63	return 0;
 64
 65fail:
 66	ceph_crypto_key_destroy(key);
 67	return ret;
 68}
 69
 70int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
 71			  const struct ceph_crypto_key *src)
 72{
 73	memcpy(dst, src, sizeof(struct ceph_crypto_key));
 74	return set_secret(dst, src->key);
 
 
 
 
 
 
 75}
 76
 77int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
 78{
 79	int ret;
 80
 81	ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad);
 82	key->type = ceph_decode_16(p);
 83	ceph_decode_copy(p, &key->created, sizeof(key->created));
 84	key->len = ceph_decode_16(p);
 85	ceph_decode_need(p, end, key->len, bad);
 86	ret = set_secret(key, *p);
 87	memzero_explicit(*p, key->len);
 88	*p += key->len;
 89	return ret;
 
 90
 91bad:
 92	dout("failed to decode crypto key\n");
 93	return -EINVAL;
 94}
 95
 96int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
 97{
 98	int inlen = strlen(inkey);
 99	int blen = inlen * 3 / 4;
100	void *buf, *p;
101	int ret;
102
103	dout("crypto_key_unarmor %s\n", inkey);
104	buf = kmalloc(blen, GFP_NOFS);
105	if (!buf)
106		return -ENOMEM;
107	blen = ceph_unarmor(buf, inkey, inkey+inlen);
108	if (blen < 0) {
109		kfree(buf);
110		return blen;
111	}
112
113	p = buf;
114	ret = ceph_crypto_key_decode(key, &p, p + blen);
115	kfree(buf);
116	if (ret)
117		return ret;
118	dout("crypto_key_unarmor key %p type %d len %d\n", key,
119	     key->type, key->len);
120	return 0;
121}
122
123void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
 
 
 
 
124{
125	if (key) {
126		kfree_sensitive(key->key);
127		key->key = NULL;
128		if (key->tfm) {
129			crypto_free_sync_skcipher(key->tfm);
130			key->tfm = NULL;
131		}
132	}
133}
134
135static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
136
137/*
138 * Should be used for buffers allocated with kvmalloc().
139 * Currently these are encrypt out-buffer (ceph_buffer) and decrypt
140 * in-buffer (msg front).
141 *
142 * Dispose of @sgt with teardown_sgtable().
143 *
144 * @prealloc_sg is to avoid memory allocation inside sg_alloc_table()
145 * in cases where a single sg is sufficient.  No attempt to reduce the
146 * number of sgs by squeezing physically contiguous pages together is
147 * made though, for simplicity.
148 */
149static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg,
150			 const void *buf, unsigned int buf_len)
151{
152	struct scatterlist *sg;
153	const bool is_vmalloc = is_vmalloc_addr(buf);
154	unsigned int off = offset_in_page(buf);
155	unsigned int chunk_cnt = 1;
156	unsigned int chunk_len = PAGE_ALIGN(off + buf_len);
157	int i;
158	int ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
160	if (buf_len == 0) {
161		memset(sgt, 0, sizeof(*sgt));
162		return -EINVAL;
163	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
165	if (is_vmalloc) {
166		chunk_cnt = chunk_len >> PAGE_SHIFT;
167		chunk_len = PAGE_SIZE;
168	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
170	if (chunk_cnt > 1) {
171		ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS);
172		if (ret)
173			return ret;
174	} else {
175		WARN_ON(chunk_cnt != 1);
176		sg_init_table(prealloc_sg, 1);
177		sgt->sgl = prealloc_sg;
178		sgt->nents = sgt->orig_nents = 1;
179	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
181	for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
182		struct page *page;
183		unsigned int len = min(chunk_len - off, buf_len);
184
185		if (is_vmalloc)
186			page = vmalloc_to_page(buf);
187		else
188			page = virt_to_page(buf);
189
190		sg_set_page(sg, page, len, off);
191
192		off = 0;
193		buf += len;
194		buf_len -= len;
 
 
 
 
 
 
 
 
 
 
195	}
196	WARN_ON(buf_len != 0);
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198	return 0;
199}
200
201static void teardown_sgtable(struct sg_table *sgt)
202{
203	if (sgt->orig_nents > 1)
204		sg_free_table(sgt);
205}
206
207static int ceph_aes_crypt(const struct ceph_crypto_key *key, bool encrypt,
208			  void *buf, int buf_len, int in_len, int *pout_len)
209{
210	SYNC_SKCIPHER_REQUEST_ON_STACK(req, key->tfm);
211	struct sg_table sgt;
212	struct scatterlist prealloc_sg;
213	char iv[AES_BLOCK_SIZE] __aligned(8);
214	int pad_byte = AES_BLOCK_SIZE - (in_len & (AES_BLOCK_SIZE - 1));
215	int crypt_len = encrypt ? in_len + pad_byte : in_len;
216	int ret;
 
217
218	WARN_ON(crypt_len > buf_len);
219	if (encrypt)
220		memset(buf + in_len, pad_byte, pad_byte);
221	ret = setup_sgtable(&sgt, &prealloc_sg, buf, crypt_len);
222	if (ret)
223		return ret;
 
 
 
 
 
 
 
224
225	memcpy(iv, aes_iv, AES_BLOCK_SIZE);
226	skcipher_request_set_sync_tfm(req, key->tfm);
227	skcipher_request_set_callback(req, 0, NULL, NULL);
228	skcipher_request_set_crypt(req, sgt.sgl, sgt.sgl, crypt_len, iv);
229
230	/*
231	print_hex_dump(KERN_ERR, "key: ", DUMP_PREFIX_NONE, 16, 1,
232		       key->key, key->len, 1);
233	print_hex_dump(KERN_ERR, " in: ", DUMP_PREFIX_NONE, 16, 1,
234		       buf, crypt_len, 1);
235	*/
236	if (encrypt)
237		ret = crypto_skcipher_encrypt(req);
 
 
 
 
 
 
 
 
 
 
238	else
239		ret = crypto_skcipher_decrypt(req);
240	skcipher_request_zero(req);
241	if (ret) {
242		pr_err("%s %scrypt failed: %d\n", __func__,
243		       encrypt ? "en" : "de", ret);
244		goto out_sgt;
 
 
 
 
 
 
 
 
245	}
246	/*
247	print_hex_dump(KERN_ERR, "out: ", DUMP_PREFIX_NONE, 16, 1,
248		       buf, crypt_len, 1);
 
 
249	*/
250
251	if (encrypt) {
252		*pout_len = crypt_len;
253	} else {
254		pad_byte = *(char *)(buf + in_len - 1);
255		if (pad_byte > 0 && pad_byte <= AES_BLOCK_SIZE &&
256		    in_len >= pad_byte) {
257			*pout_len = in_len - pad_byte;
258		} else {
259			pr_err("%s got bad padding %d on in_len %d\n",
260			       __func__, pad_byte, in_len);
261			ret = -EPERM;
262			goto out_sgt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263		}
 
 
 
 
 
 
 
 
 
264	}
 
265
266out_sgt:
267	teardown_sgtable(&sgt);
268	return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269}
270
271int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt,
272	       void *buf, int buf_len, int in_len, int *pout_len)
 
273{
274	switch (key->type) {
275	case CEPH_CRYPTO_NONE:
276		*pout_len = in_len;
 
 
 
 
277		return 0;
 
278	case CEPH_CRYPTO_AES:
279		return ceph_aes_crypt(key, encrypt, buf, buf_len, in_len,
280				      pout_len);
 
281	default:
282		return -ENOTSUPP;
283	}
284}
285
286static int ceph_key_preparse(struct key_preparsed_payload *prep)
 
287{
288	struct ceph_crypto_key *ckey;
289	size_t datalen = prep->datalen;
290	int ret;
291	void *p;
292
293	ret = -EINVAL;
294	if (datalen <= 0 || datalen > 32767 || !prep->data)
295		goto err;
296
 
 
 
 
297	ret = -ENOMEM;
298	ckey = kmalloc(sizeof(*ckey), GFP_KERNEL);
299	if (!ckey)
300		goto err;
301
302	/* TODO ceph_crypto_key_decode should really take const input */
303	p = (void *)prep->data;
304	ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen);
305	if (ret < 0)
306		goto err_ckey;
307
308	prep->payload.data[0] = ckey;
309	prep->quotalen = datalen;
310	return 0;
311
312err_ckey:
313	kfree(ckey);
314err:
315	return ret;
316}
317
318static void ceph_key_free_preparse(struct key_preparsed_payload *prep)
319{
320	struct ceph_crypto_key *ckey = prep->payload.data[0];
321	ceph_crypto_key_destroy(ckey);
322	kfree(ckey);
323}
324
325static void ceph_key_destroy(struct key *key)
326{
327	struct ceph_crypto_key *ckey = key->payload.data[0];
328
329	ceph_crypto_key_destroy(ckey);
330	kfree(ckey);
331}
332
333struct key_type key_type_ceph = {
334	.name		= "ceph",
335	.preparse	= ceph_key_preparse,
336	.free_preparse	= ceph_key_free_preparse,
337	.instantiate	= generic_key_instantiate,
338	.destroy	= ceph_key_destroy,
339};
340
341int __init ceph_crypto_init(void)
342{
343	return register_key_type(&key_type_ceph);
344}
345
346void ceph_crypto_shutdown(void)
347{
348	unregister_key_type(&key_type_ceph);
349}
v3.15
 
  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
 14int 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
 24int 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
 36int 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
 49bad:
 50	dout("failed to decode crypto key\n");
 51	return -EINVAL;
 52}
 53
 54int 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
 85static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
 86{
 87	return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
 
 
 
 
 
 
 
 88}
 89
 90static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
 91
 92static 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
142static 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
196static 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
256static 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
331int 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
351int 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
384int 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
404int 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
426static 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
456err_ckey:
457	kfree(ckey);
458err:
459	return ret;
460}
461
462static int ceph_key_match(const struct key *key, const void *description)
463{
464	return strcmp(key->description, description) == 0;
 
 
465}
466
467static 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
474struct 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
481int ceph_crypto_init(void) {
 
482	return register_key_type(&key_type_ceph);
483}
484
485void ceph_crypto_shutdown(void) {
 
486	unregister_key_type(&key_type_ceph);
487}