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