Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libceph: introduce ceph_crypto_key_prepare()

In preparation for bringing in a new encryption scheme/key type,
decouple decoding or cloning the key from allocating required crypto
API objects and setting them up. The rationale is that a) in some
cases a shallow clone is sufficient and b) ceph_crypto_key_prepare()
may grow additional parameters that would be inconvenient to provide
at the point the key is originally decoded.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

+57 -43
+20 -6
net/ceph/auth_x.c
··· 221 221 if (ret) 222 222 goto out; 223 223 224 + ret = ceph_crypto_key_prepare(&new_session_key); 225 + if (ret) 226 + goto out; 227 + 224 228 ceph_decode_need(&dp, dend, sizeof(struct ceph_timespec), bad); 225 229 ceph_decode_timespec64(&validity, dp); 226 230 dp += sizeof(struct ceph_timespec); ··· 381 377 382 378 ceph_crypto_key_destroy(&au->session_key); 383 379 ret = ceph_crypto_key_clone(&au->session_key, &th->session_key); 380 + if (ret) 381 + goto out_au; 382 + 383 + ret = ceph_crypto_key_prepare(&au->session_key); 384 384 if (ret) 385 385 goto out_au; 386 386 ··· 1114 1106 int ret; 1115 1107 1116 1108 dout("ceph_x_init %p\n", ac); 1117 - ret = -ENOMEM; 1118 1109 xi = kzalloc(sizeof(*xi), GFP_NOFS); 1119 1110 if (!xi) 1120 - goto out; 1111 + return -ENOMEM; 1121 1112 1122 1113 ret = -EINVAL; 1123 1114 if (!ac->key) { 1124 1115 pr_err("no secret set (for auth_x protocol)\n"); 1125 - goto out_nomem; 1116 + goto err_xi; 1126 1117 } 1127 1118 1128 1119 ret = ceph_crypto_key_clone(&xi->secret, ac->key); 1129 1120 if (ret < 0) { 1130 1121 pr_err("cannot clone key: %d\n", ret); 1131 - goto out_nomem; 1122 + goto err_xi; 1123 + } 1124 + 1125 + ret = ceph_crypto_key_prepare(&xi->secret); 1126 + if (ret) { 1127 + pr_err("cannot prepare key: %d\n", ret); 1128 + goto err_secret; 1132 1129 } 1133 1130 1134 1131 xi->starting = true; ··· 1144 1131 ac->ops = &ceph_x_ops; 1145 1132 return 0; 1146 1133 1147 - out_nomem: 1134 + err_secret: 1135 + ceph_crypto_key_destroy(&xi->secret); 1136 + err_xi: 1148 1137 kfree(xi); 1149 - out: 1150 1138 return ret; 1151 1139 }
+36 -37
net/ceph/crypto.c
··· 16 16 #include <linux/ceph/decode.h> 17 17 #include "crypto.h" 18 18 19 - /* 20 - * Set ->key and ->tfm. The rest of the key should be filled in before 21 - * this function is called. 22 - */ 23 - static int set_secret(struct ceph_crypto_key *key, void *buf) 19 + static int set_aes_tfm(struct ceph_crypto_key *key) 24 20 { 25 21 unsigned int noio_flag; 26 22 int ret; 27 23 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 - key->key = kmemdup(buf, key->len, GFP_NOIO); 41 - if (!key->key) { 42 - ret = -ENOMEM; 43 - goto fail; 44 - } 45 - 46 - /* crypto_alloc_sync_skcipher() allocates with GFP_KERNEL */ 47 24 noio_flag = memalloc_noio_save(); 48 25 key->tfm = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0); 49 26 memalloc_noio_restore(noio_flag); 50 27 if (IS_ERR(key->tfm)) { 51 28 ret = PTR_ERR(key->tfm); 52 29 key->tfm = NULL; 53 - goto fail; 30 + return ret; 54 31 } 55 32 56 33 ret = crypto_sync_skcipher_setkey(key->tfm, key->key, key->len); 57 34 if (ret) 58 - goto fail; 35 + return ret; 59 36 60 37 return 0; 61 - 62 - fail: 63 - ceph_crypto_key_destroy(key); 64 - return ret; 65 38 } 66 39 40 + int ceph_crypto_key_prepare(struct ceph_crypto_key *key) 41 + { 42 + switch (key->type) { 43 + case CEPH_CRYPTO_NONE: 44 + return 0; /* nothing to do */ 45 + case CEPH_CRYPTO_AES: 46 + return set_aes_tfm(key); 47 + default: 48 + return -ENOTSUPP; 49 + } 50 + } 51 + 52 + /* 53 + * @dst should be zeroed before this function is called. 54 + */ 67 55 int ceph_crypto_key_clone(struct ceph_crypto_key *dst, 68 56 const struct ceph_crypto_key *src) 69 57 { 70 - memcpy(dst, src, sizeof(struct ceph_crypto_key)); 71 - return set_secret(dst, src->key); 58 + dst->type = src->type; 59 + dst->created = src->created; 60 + dst->len = src->len; 61 + 62 + dst->key = kmemdup(src->key, src->len, GFP_NOIO); 63 + if (!dst->key) 64 + return -ENOMEM; 65 + 66 + return 0; 72 67 } 73 68 69 + /* 70 + * @key should be zeroed before this function is called. 71 + */ 74 72 int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) 75 73 { 76 - int ret; 77 - 78 74 ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad); 79 75 key->type = ceph_decode_16(p); 80 76 ceph_decode_copy(p, &key->created, sizeof(key->created)); ··· 81 85 return -EINVAL; 82 86 } 83 87 84 - ret = set_secret(key, *p); 88 + key->key = kmemdup(*p, key->len, GFP_NOIO); 89 + if (!key->key) 90 + return -ENOMEM; 91 + 85 92 memzero_explicit(*p, key->len); 86 93 *p += key->len; 87 - return ret; 94 + return 0; 88 95 89 96 bad: 90 97 dout("failed to decode crypto key\n"); ··· 321 322 goto err; 322 323 323 324 ret = -ENOMEM; 324 - ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); 325 + ckey = kzalloc(sizeof(*ckey), GFP_KERNEL); 325 326 if (!ckey) 326 327 goto err; 327 328
+1
net/ceph/crypto.h
··· 19 19 struct crypto_sync_skcipher *tfm; 20 20 }; 21 21 22 + int ceph_crypto_key_prepare(struct ceph_crypto_key *key); 22 23 int ceph_crypto_key_clone(struct ceph_crypto_key *dst, 23 24 const struct ceph_crypto_key *src); 24 25 int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end);