18b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 23d14c5d2b6e15c21d8e5467dc62d33127c23a644Yehuda Sadeh#include <linux/ceph/ceph_debug.h> 38b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 48b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil#include <linux/err.h> 58b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil#include <linux/scatterlist.h> 65a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 78b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil#include <crypto/hash.h> 84b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen#include <linux/key-type.h> 98b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 104b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen#include <keys/ceph-type.h> 117c3bec0a1f2cba8a01b505f032a75cfb8d5cd56dDavid Howells#include <keys/user-type.h> 123d14c5d2b6e15c21d8e5467dc62d33127c23a644Yehuda Sadeh#include <linux/ceph/decode.h> 138b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil#include "crypto.h" 148b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 158323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanenint ceph_crypto_key_clone(struct ceph_crypto_key *dst, 168323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen const struct ceph_crypto_key *src) 178323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen{ 188323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen memcpy(dst, src, sizeof(struct ceph_crypto_key)); 19186482560f660b8dbf77ee43aa6489cb45d342cdThomas Meyer dst->key = kmemdup(src->key, src->len, GFP_NOFS); 208323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen if (!dst->key) 218323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen return -ENOMEM; 228323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen return 0; 238323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen} 248323c3aa74cd92465350294567142d12ffdcc963Tommi Virtanen 258b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) 268b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 278b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (*p + sizeof(u16) + sizeof(key->created) + 288b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sizeof(u16) + key->len > end) 298b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ERANGE; 308b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_encode_16(p, key->type); 318b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_encode_copy(p, &key->created, sizeof(key->created)); 328b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_encode_16(p, key->len); 338b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_encode_copy(p, key->key, key->len); 348b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 358b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 368b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 378b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) 388b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 398b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad); 408b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key->type = ceph_decode_16(p); 418b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_decode_copy(p, &key->created, sizeof(key->created)); 428b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key->len = ceph_decode_16(p); 438b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_decode_need(p, end, key->len, bad); 448b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key->key = kmalloc(key->len, GFP_NOFS); 458b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (!key->key) 468b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ENOMEM; 478b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ceph_decode_copy(p, key->key, key->len); 488b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 498b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 508b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilbad: 518b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dout("failed to decode crypto key\n"); 528b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EINVAL; 538b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 548b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 558b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey) 568b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 578b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int inlen = strlen(inkey); 588b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int blen = inlen * 3 / 4; 598b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *buf, *p; 608b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ret; 618b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 628b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dout("crypto_key_unarmor %s\n", inkey); 638b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil buf = kmalloc(blen, GFP_NOFS); 648b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (!buf) 658b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ENOMEM; 668b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil blen = ceph_unarmor(buf, inkey, inkey+inlen); 678b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (blen < 0) { 688b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil kfree(buf); 698b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return blen; 708b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 718b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 728b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil p = buf; 738b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ret = ceph_crypto_key_decode(key, &p, p + blen); 748b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil kfree(buf); 758b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (ret) 768b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return ret; 778b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dout("crypto_key_unarmor key %p type %d len %d\n", key, 788b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key->type, key->len); 798b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 808b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 818b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 828b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 838b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 848b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil#define AES_KEY_SIZE 16 858b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 868b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilstatic struct crypto_blkcipher *ceph_crypto_alloc_cipher(void) 878b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 888b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); 898b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 908b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 91cbbfe499055f49c09210e04d9f88c2f483052384Sage Weilstatic const u8 *aes_iv = (u8 *)CEPH_AES_IV; 928b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 93aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov/* 94aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * Should be used for buffers allocated with ceph_kvmalloc(). 95aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * Currently these are encrypt out-buffer (ceph_buffer) and decrypt 96aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * in-buffer (msg front). 97aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * 98aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * Dispose of @sgt with teardown_sgtable(). 99aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * 100aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * @prealloc_sg is to avoid memory allocation inside sg_alloc_table() 101aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * in cases where a single sg is sufficient. No attempt to reduce the 102aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * number of sgs by squeezing physically contiguous pages together is 103aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov * made though, for simplicity. 104aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov */ 105aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovstatic int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg, 106aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov const void *buf, unsigned int buf_len) 107aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov{ 108aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct scatterlist *sg; 109aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov const bool is_vmalloc = is_vmalloc_addr(buf); 110aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov unsigned int off = offset_in_page(buf); 111aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov unsigned int chunk_cnt = 1; 112aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov unsigned int chunk_len = PAGE_ALIGN(off + buf_len); 113aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov int i; 114aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov int ret; 115aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 116aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (buf_len == 0) { 117aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov memset(sgt, 0, sizeof(*sgt)); 118aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return -EINVAL; 119aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } 120aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 121aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (is_vmalloc) { 122aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov chunk_cnt = chunk_len >> PAGE_SHIFT; 123aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov chunk_len = PAGE_SIZE; 124aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } 125aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 126aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (chunk_cnt > 1) { 127aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS); 128aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret) 129aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return ret; 130aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } else { 131aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov WARN_ON(chunk_cnt != 1); 132aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov sg_init_table(prealloc_sg, 1); 133aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov sgt->sgl = prealloc_sg; 134aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov sgt->nents = sgt->orig_nents = 1; 135aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } 136aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 137aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { 138aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct page *page; 139aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov unsigned int len = min(chunk_len - off, buf_len); 140aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 141aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (is_vmalloc) 142aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov page = vmalloc_to_page(buf); 143aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov else 144aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov page = virt_to_page(buf); 145aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 146aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov sg_set_page(sg, page, len, off); 147aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 148aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov off = 0; 149aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov buf += len; 150aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov buf_len -= len; 151aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } 152aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov WARN_ON(buf_len != 0); 153aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 154aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return 0; 155aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov} 156aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 157aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovstatic void teardown_sgtable(struct sg_table *sgt) 158aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov{ 159aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (sgt->orig_nents > 1) 160aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov sg_free_table(sgt); 161aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov} 162aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 163cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadehstatic int ceph_aes_encrypt(const void *key, int key_len, 164cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh void *dst, size_t *dst_len, 165cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh const void *src, size_t src_len) 1668b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 167aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct scatterlist sg_in[2], prealloc_sg; 168aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct sg_table sg_out; 1698b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); 1708b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; 1718b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ret; 1728b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *iv; 1738b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ivsize; 1748b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil size_t zero_padding = (0x10 - (src_len & 0x0f)); 1758b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil char pad[16]; 1768b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 1778b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (IS_ERR(tfm)) 1788b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return PTR_ERR(tfm); 1798b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 1808b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memset(pad, zero_padding, zero_padding); 1818b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 1828b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst_len = src_len + zero_padding; 1838b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 1848b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_init_table(sg_in, 2); 1858b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_in[0], src, src_len); 1868b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_in[1], pad, zero_padding); 187aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); 188aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret) 189aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_tfm; 190aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 191aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_blkcipher_setkey((void *)tfm, key, key_len); 1928b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil iv = crypto_blkcipher_crt(tfm)->iv; 1938b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ivsize = crypto_blkcipher_ivsize(tfm); 1948b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(iv, aes_iv, ivsize); 195aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 1968b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 1978b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, 1988b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key, key_len, 1); 1998b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc src: ", DUMP_PREFIX_NONE, 16, 1, 2008b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src, src_len, 1); 2018b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, 2028b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pad, zero_padding, 1); 2038b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 204aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, 2058b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src_len + zero_padding); 206aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret < 0) { 2078b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pr_err("ceph_aes_crypt failed %d\n", ret); 208aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_sg; 209aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } 2108b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 2118b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, 2128b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst, *dst_len, 1); 2138b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 214aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 215aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_sg: 216aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov teardown_sgtable(&sg_out); 217aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_tfm: 218aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_free_blkcipher(tfm); 219aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return ret; 2208b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 2218b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 222cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadehstatic int ceph_aes_encrypt2(const void *key, int key_len, void *dst, 223cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh size_t *dst_len, 224cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh const void *src1, size_t src1_len, 225cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh const void *src2, size_t src2_len) 2268b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 227aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct scatterlist sg_in[3], prealloc_sg; 228aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct sg_table sg_out; 2298b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); 2308b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; 2318b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ret; 2328b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *iv; 2338b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ivsize; 2348b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f)); 2358b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil char pad[16]; 2368b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 2378b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (IS_ERR(tfm)) 2388b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return PTR_ERR(tfm); 2398b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 2408b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memset(pad, zero_padding, zero_padding); 2418b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 2428b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst_len = src1_len + src2_len + zero_padding; 2438b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 2448b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_init_table(sg_in, 3); 2458b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_in[0], src1, src1_len); 2468b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_in[1], src2, src2_len); 2478b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_in[2], pad, zero_padding); 248aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); 249aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret) 250aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_tfm; 251aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 252aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_blkcipher_setkey((void *)tfm, key, key_len); 2538b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil iv = crypto_blkcipher_crt(tfm)->iv; 2548b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ivsize = crypto_blkcipher_ivsize(tfm); 2558b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(iv, aes_iv, ivsize); 256aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 2578b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 2588b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, 2598b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key, key_len, 1); 2608b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc src1: ", DUMP_PREFIX_NONE, 16, 1, 2618b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src1, src1_len, 1); 2628b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc src2: ", DUMP_PREFIX_NONE, 16, 1, 2638b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src2, src2_len, 1); 2648b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, 2658b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pad, zero_padding, 1); 2668b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 267aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, 2688b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src1_len + src2_len + zero_padding); 269aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret < 0) { 2708b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pr_err("ceph_aes_crypt2 failed %d\n", ret); 271aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_sg; 272aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov } 2738b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 2748b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, 2758b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst, *dst_len, 1); 2768b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 277aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 278aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_sg: 279aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov teardown_sgtable(&sg_out); 280aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_tfm: 281aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_free_blkcipher(tfm); 282aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return ret; 2838b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 2848b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 285cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadehstatic int ceph_aes_decrypt(const void *key, int key_len, 286cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh void *dst, size_t *dst_len, 287cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh const void *src, size_t src_len) 2888b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 289aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct sg_table sg_in; 290aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct scatterlist sg_out[2], prealloc_sg; 2918b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); 2928b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct blkcipher_desc desc = { .tfm = tfm }; 2938b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil char pad[16]; 2948b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *iv; 2958b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ivsize; 2968b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ret; 2978b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int last_byte; 2988b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 2998b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (IS_ERR(tfm)) 3008b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return PTR_ERR(tfm); 3018b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3028b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_init_table(sg_out, 2); 3038b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_out[0], dst, *dst_len); 3048b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_out[1], pad, sizeof(pad)); 305aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); 306aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret) 307aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_tfm; 3088b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 309aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_blkcipher_setkey((void *)tfm, key, key_len); 3108b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil iv = crypto_blkcipher_crt(tfm)->iv; 3118b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ivsize = crypto_blkcipher_ivsize(tfm); 3128b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(iv, aes_iv, ivsize); 3138b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3148b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 3158b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1, 3168b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key, key_len, 1); 3178b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, 3188b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src, src_len, 1); 3198b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 320aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); 3218b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (ret < 0) { 3228b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pr_err("ceph_aes_decrypt failed %d\n", ret); 323aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_sg; 3248b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 3258b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3268b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (src_len <= *dst_len) 3278b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte = ((char *)dst)[src_len - 1]; 3288b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil else 3298b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte = pad[src_len - *dst_len - 1]; 3308b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (last_byte <= 16 && src_len >= last_byte) { 3318b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst_len = src_len - last_byte; 3328b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } else { 3338b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n", 3348b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte, (int)src_len); 3358b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EPERM; /* bad padding */ 3368b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 3378b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 3388b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1, 3398b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst, *dst_len, 1); 3408b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 341aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov 342aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_sg: 343aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov teardown_sgtable(&sg_in); 344aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_tfm: 345aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_free_blkcipher(tfm); 346aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return ret; 3478b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 3488b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 349cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadehstatic int ceph_aes_decrypt2(const void *key, int key_len, 350cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh void *dst1, size_t *dst1_len, 351cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh void *dst2, size_t *dst2_len, 352cd84db6e4051a9fb7941d49d31a0193a3371fd61Yehuda Sadeh const void *src, size_t src_len) 3538b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 354aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct sg_table sg_in; 355aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov struct scatterlist sg_out[3], prealloc_sg; 3568b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); 3578b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil struct blkcipher_desc desc = { .tfm = tfm }; 3588b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil char pad[16]; 3598b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *iv; 3608b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ivsize; 3618b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int ret; 3628b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil int last_byte; 3638b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3648b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (IS_ERR(tfm)) 3658b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return PTR_ERR(tfm); 3668b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3678b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_init_table(sg_out, 3); 3688b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_out[0], dst1, *dst1_len); 3698b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_out[1], dst2, *dst2_len); 3708b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil sg_set_buf(&sg_out[2], pad, sizeof(pad)); 371aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); 372aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov if (ret) 373aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_tfm; 3748b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3758b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil crypto_blkcipher_setkey((void *)tfm, key, key_len); 3768b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil iv = crypto_blkcipher_crt(tfm)->iv; 3778b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil ivsize = crypto_blkcipher_ivsize(tfm); 3788b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(iv, aes_iv, ivsize); 3798b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3808b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 3818b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1, 3828b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil key, key_len, 1); 3838b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, 3848b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src, src_len, 1); 3858b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 386aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); 3878b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (ret < 0) { 3888b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pr_err("ceph_aes_decrypt failed %d\n", ret); 389aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov goto out_sg; 3908b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 3918b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 3928b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (src_len <= *dst1_len) 3938b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte = ((char *)dst1)[src_len - 1]; 3948b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil else if (src_len <= *dst1_len + *dst2_len) 3958b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte = ((char *)dst2)[src_len - *dst1_len - 1]; 3968b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil else 3978b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte = pad[src_len - *dst1_len - *dst2_len - 1]; 3988b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (last_byte <= 16 && src_len >= last_byte) { 3998b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src_len -= last_byte; 4008b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } else { 4018b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n", 4028b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil last_byte, (int)src_len); 4038b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EPERM; /* bad padding */ 4048b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 4058b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4068b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (src_len < *dst1_len) { 4078b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst1_len = src_len; 4088b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst2_len = 0; 4098b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } else { 4108b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst2_len = src_len - *dst1_len; 4118b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 4128b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil /* 4138b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec out1: ", DUMP_PREFIX_NONE, 16, 1, 4148b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst1, *dst1_len, 1); 4158b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil print_hex_dump(KERN_ERR, "dec out2: ", DUMP_PREFIX_NONE, 16, 1, 4168b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst2, *dst2_len, 1); 4178b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil */ 4188b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 419aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_sg: 420aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov teardown_sgtable(&sg_in); 421aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomovout_tfm: 422aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov crypto_free_blkcipher(tfm); 423aaef31703a0cf6a733e651885bfb49edc3ac6774Ilya Dryomov return ret; 4248b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 4258b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4268b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4278b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_decrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, 4288b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil const void *src, size_t src_len) 4298b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 4308b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil switch (secret->type) { 4318b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_NONE: 4328b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (*dst_len < src_len) 4338b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ERANGE; 4348b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(dst, src, src_len); 4358b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst_len = src_len; 4368b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 4378b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4388b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_AES: 4398b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return ceph_aes_decrypt(secret->key, secret->len, dst, 4408b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst_len, src, src_len); 4418b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4428b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil default: 4438b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EINVAL; 4448b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 4458b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 4468b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4478b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_decrypt2(struct ceph_crypto_key *secret, 4488b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *dst1, size_t *dst1_len, 4498b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil void *dst2, size_t *dst2_len, 4508b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil const void *src, size_t src_len) 4518b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 4528b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil size_t t; 4538b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4548b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil switch (secret->type) { 4558b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_NONE: 4568b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (*dst1_len + *dst2_len < src_len) 4578b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ERANGE; 4588b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil t = min(*dst1_len, src_len); 4598b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(dst1, src, t); 4608b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst1_len = t; 4618b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src += t; 4628b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src_len -= t; 4638b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (src_len) { 4648b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil t = min(*dst2_len, src_len); 4658b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(dst2, src, t); 4668b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst2_len = t; 4678b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 4688b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 4698b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4708b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_AES: 4718b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return ceph_aes_decrypt2(secret->key, secret->len, 4728b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst1, dst1_len, dst2, dst2_len, 4738b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src, src_len); 4748b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4758b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil default: 4768b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EINVAL; 4778b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 4788b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 4798b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4808b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_encrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, 4818b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil const void *src, size_t src_len) 4828b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 4838b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil switch (secret->type) { 4848b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_NONE: 4858b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (*dst_len < src_len) 4868b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ERANGE; 4878b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(dst, src, src_len); 4888b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst_len = src_len; 4898b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 4908b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4918b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_AES: 4928b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return ceph_aes_encrypt(secret->key, secret->len, dst, 4938b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil dst_len, src, src_len); 4948b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 4958b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil default: 4968b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EINVAL; 4978b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 4988b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 4998b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 5008b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weilint ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, 5018b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil const void *src1, size_t src1_len, 5028b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil const void *src2, size_t src2_len) 5038b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil{ 5048b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil switch (secret->type) { 5058b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_NONE: 5068b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil if (*dst_len < src1_len + src2_len) 5078b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -ERANGE; 5088b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(dst, src1, src1_len); 5098b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil memcpy(dst + src1_len, src2, src2_len); 5108b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil *dst_len = src1_len + src2_len; 5118b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return 0; 5128b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 5138b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil case CEPH_CRYPTO_AES: 5148b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return ceph_aes_encrypt2(secret->key, secret->len, dst, dst_len, 5158b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil src1, src1_len, src2, src2_len); 5168b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil 5178b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil default: 5188b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil return -EINVAL; 5198b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil } 5208b6e4f2d8b21c25225b1ce8d53a2e03b92cc8522Sage Weil} 5214b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 522efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howellsstatic int ceph_key_preparse(struct key_preparsed_payload *prep) 5234b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen{ 5244b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen struct ceph_crypto_key *ckey; 525cf7f601c067994f371ba77721d1e45fce61a4569David Howells size_t datalen = prep->datalen; 5264b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen int ret; 5274b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen void *p; 5284b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5294b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen ret = -EINVAL; 530cf7f601c067994f371ba77721d1e45fce61a4569David Howells if (datalen <= 0 || datalen > 32767 || !prep->data) 5314b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen goto err; 5324b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5334b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen ret = -ENOMEM; 5344b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); 5354b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen if (!ckey) 5364b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen goto err; 5374b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5384b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen /* TODO ceph_crypto_key_decode should really take const input */ 539cf7f601c067994f371ba77721d1e45fce61a4569David Howells p = (void *)prep->data; 540cf7f601c067994f371ba77721d1e45fce61a4569David Howells ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); 5414b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen if (ret < 0) 5424b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen goto err_ckey; 5434b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 544efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells prep->payload[0] = ckey; 545efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells prep->quotalen = datalen; 5464b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen return 0; 5474b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5484b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanenerr_ckey: 5494b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen kfree(ckey); 5504b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanenerr: 5514b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen return ret; 5524b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen} 5534b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 554efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howellsstatic void ceph_key_free_preparse(struct key_preparsed_payload *prep) 555efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells{ 556efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells struct ceph_crypto_key *ckey = prep->payload[0]; 557efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells ceph_crypto_key_destroy(ckey); 558efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells kfree(ckey); 559efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells} 560efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells 561efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howellsstatic void ceph_key_destroy(struct key *key) 562efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells{ 5634b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen struct ceph_crypto_key *ckey = key->payload.data; 5644b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5654b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen ceph_crypto_key_destroy(ckey); 566f0666b1ac875ff32fe290219b150ec62eebbe10eSylvain Munaut kfree(ckey); 5674b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen} 5684b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5694b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanenstruct key_type key_type_ceph = { 5704b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen .name = "ceph", 571efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells .preparse = ceph_key_preparse, 572efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells .free_preparse = ceph_key_free_preparse, 573efa64c0978a1fb3de8bca6f931b9858c3e371f1fDavid Howells .instantiate = generic_key_instantiate, 5744b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen .destroy = ceph_key_destroy, 5754b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen}; 5764b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5774b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanenint ceph_crypto_init(void) { 5784b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen return register_key_type(&key_type_ceph); 5794b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen} 5804b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen 5814b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanenvoid ceph_crypto_shutdown(void) { 5824b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen unregister_key_type(&key_type_ceph); 5834b2a58abd1e17c0ee53c8dded879e015917cca67Tommi Virtanen} 584