/fs/ceph/crypto.c

https://github.com/buber82/htc-kernel-msm7227-exp · C · 409 lines · 303 code · 58 blank · 48 comment · 34 complexity · d010e21fe3787964734d43501925ca14 MD5 · raw file

  1. #include "ceph_debug.h"
  2. #include <linux/err.h>
  3. #include <linux/scatterlist.h>
  4. #include <linux/slab.h>
  5. #include <crypto/hash.h>
  6. #include "crypto.h"
  7. #include "decode.h"
  8. int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
  9. {
  10. if (*p + sizeof(u16) + sizeof(key->created) +
  11. sizeof(u16) + key->len > end)
  12. return -ERANGE;
  13. ceph_encode_16(p, key->type);
  14. ceph_encode_copy(p, &key->created, sizeof(key->created));
  15. ceph_encode_16(p, key->len);
  16. ceph_encode_copy(p, key->key, key->len);
  17. return 0;
  18. }
  19. int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
  20. {
  21. ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad);
  22. key->type = ceph_decode_16(p);
  23. ceph_decode_copy(p, &key->created, sizeof(key->created));
  24. key->len = ceph_decode_16(p);
  25. ceph_decode_need(p, end, key->len, bad);
  26. key->key = kmalloc(key->len, GFP_NOFS);
  27. if (!key->key)
  28. return -ENOMEM;
  29. ceph_decode_copy(p, key->key, key->len);
  30. return 0;
  31. bad:
  32. dout("failed to decode crypto key\n");
  33. return -EINVAL;
  34. }
  35. int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
  36. {
  37. int inlen = strlen(inkey);
  38. int blen = inlen * 3 / 4;
  39. void *buf, *p;
  40. int ret;
  41. dout("crypto_key_unarmor %s\n", inkey);
  42. buf = kmalloc(blen, GFP_NOFS);
  43. if (!buf)
  44. return -ENOMEM;
  45. blen = ceph_unarmor(buf, inkey, inkey+inlen);
  46. if (blen < 0) {
  47. kfree(buf);
  48. return blen;
  49. }
  50. p = buf;
  51. ret = ceph_crypto_key_decode(key, &p, p + blen);
  52. kfree(buf);
  53. if (ret)
  54. return ret;
  55. dout("crypto_key_unarmor key %p type %d len %d\n", key,
  56. key->type, key->len);
  57. return 0;
  58. }
  59. #define AES_KEY_SIZE 16
  60. static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
  61. {
  62. return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
  63. }
  64. const u8 *aes_iv = "cephsageyudagreg";
  65. int ceph_aes_encrypt(const void *key, int key_len, void *dst, size_t *dst_len,
  66. const void *src, size_t src_len)
  67. {
  68. struct scatterlist sg_in[2], sg_out[1];
  69. struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
  70. struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
  71. int ret;
  72. void *iv;
  73. int ivsize;
  74. size_t zero_padding = (0x10 - (src_len & 0x0f));
  75. char pad[16];
  76. if (IS_ERR(tfm))
  77. return PTR_ERR(tfm);
  78. memset(pad, zero_padding, zero_padding);
  79. *dst_len = src_len + zero_padding;
  80. crypto_blkcipher_setkey((void *)tfm, key, key_len);
  81. sg_init_table(sg_in, 2);
  82. sg_set_buf(&sg_in[0], src, src_len);
  83. sg_set_buf(&sg_in[1], pad, zero_padding);
  84. sg_init_table(sg_out, 1);
  85. sg_set_buf(sg_out, dst, *dst_len);
  86. iv = crypto_blkcipher_crt(tfm)->iv;
  87. ivsize = crypto_blkcipher_ivsize(tfm);
  88. memcpy(iv, aes_iv, ivsize);
  89. /*
  90. print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
  91. key, key_len, 1);
  92. print_hex_dump(KERN_ERR, "enc src: ", DUMP_PREFIX_NONE, 16, 1,
  93. src, src_len, 1);
  94. print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
  95. pad, zero_padding, 1);
  96. */
  97. ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
  98. src_len + zero_padding);
  99. crypto_free_blkcipher(tfm);
  100. if (ret < 0)
  101. pr_err("ceph_aes_crypt failed %d\n", ret);
  102. /*
  103. print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
  104. dst, *dst_len, 1);
  105. */
  106. return 0;
  107. }
  108. int ceph_aes_encrypt2(const void *key, int key_len, void *dst, size_t *dst_len,
  109. const void *src1, size_t src1_len,
  110. const void *src2, size_t src2_len)
  111. {
  112. struct scatterlist sg_in[3], sg_out[1];
  113. struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
  114. struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
  115. int ret;
  116. void *iv;
  117. int ivsize;
  118. size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f));
  119. char pad[16];
  120. if (IS_ERR(tfm))
  121. return PTR_ERR(tfm);
  122. memset(pad, zero_padding, zero_padding);
  123. *dst_len = src1_len + src2_len + zero_padding;
  124. crypto_blkcipher_setkey((void *)tfm, key, key_len);
  125. sg_init_table(sg_in, 3);
  126. sg_set_buf(&sg_in[0], src1, src1_len);
  127. sg_set_buf(&sg_in[1], src2, src2_len);
  128. sg_set_buf(&sg_in[2], pad, zero_padding);
  129. sg_init_table(sg_out, 1);
  130. sg_set_buf(sg_out, dst, *dst_len);
  131. iv = crypto_blkcipher_crt(tfm)->iv;
  132. ivsize = crypto_blkcipher_ivsize(tfm);
  133. memcpy(iv, aes_iv, ivsize);
  134. /*
  135. print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
  136. key, key_len, 1);
  137. print_hex_dump(KERN_ERR, "enc src1: ", DUMP_PREFIX_NONE, 16, 1,
  138. src1, src1_len, 1);
  139. print_hex_dump(KERN_ERR, "enc src2: ", DUMP_PREFIX_NONE, 16, 1,
  140. src2, src2_len, 1);
  141. print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
  142. pad, zero_padding, 1);
  143. */
  144. ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
  145. src1_len + src2_len + zero_padding);
  146. crypto_free_blkcipher(tfm);
  147. if (ret < 0)
  148. pr_err("ceph_aes_crypt2 failed %d\n", ret);
  149. /*
  150. print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
  151. dst, *dst_len, 1);
  152. */
  153. return 0;
  154. }
  155. int ceph_aes_decrypt(const void *key, int key_len, void *dst, size_t *dst_len,
  156. const void *src, size_t src_len)
  157. {
  158. struct scatterlist sg_in[1], sg_out[2];
  159. struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
  160. struct blkcipher_desc desc = { .tfm = tfm };
  161. char pad[16];
  162. void *iv;
  163. int ivsize;
  164. int ret;
  165. int last_byte;
  166. if (IS_ERR(tfm))
  167. return PTR_ERR(tfm);
  168. crypto_blkcipher_setkey((void *)tfm, key, key_len);
  169. sg_init_table(sg_in, 1);
  170. sg_init_table(sg_out, 2);
  171. sg_set_buf(sg_in, src, src_len);
  172. sg_set_buf(&sg_out[0], dst, *dst_len);
  173. sg_set_buf(&sg_out[1], pad, sizeof(pad));
  174. iv = crypto_blkcipher_crt(tfm)->iv;
  175. ivsize = crypto_blkcipher_ivsize(tfm);
  176. memcpy(iv, aes_iv, ivsize);
  177. /*
  178. print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1,
  179. key, key_len, 1);
  180. print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1,
  181. src, src_len, 1);
  182. */
  183. ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
  184. crypto_free_blkcipher(tfm);
  185. if (ret < 0) {
  186. pr_err("ceph_aes_decrypt failed %d\n", ret);
  187. return ret;
  188. }
  189. if (src_len <= *dst_len)
  190. last_byte = ((char *)dst)[src_len - 1];
  191. else
  192. last_byte = pad[src_len - *dst_len - 1];
  193. if (last_byte <= 16 && src_len >= last_byte) {
  194. *dst_len = src_len - last_byte;
  195. } else {
  196. pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
  197. last_byte, (int)src_len);
  198. return -EPERM; /* bad padding */
  199. }
  200. /*
  201. print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
  202. dst, *dst_len, 1);
  203. */
  204. return 0;
  205. }
  206. int ceph_aes_decrypt2(const void *key, int key_len,
  207. void *dst1, size_t *dst1_len,
  208. void *dst2, size_t *dst2_len,
  209. const void *src, size_t src_len)
  210. {
  211. struct scatterlist sg_in[1], sg_out[3];
  212. struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
  213. struct blkcipher_desc desc = { .tfm = tfm };
  214. char pad[16];
  215. void *iv;
  216. int ivsize;
  217. int ret;
  218. int last_byte;
  219. if (IS_ERR(tfm))
  220. return PTR_ERR(tfm);
  221. sg_init_table(sg_in, 1);
  222. sg_set_buf(sg_in, src, src_len);
  223. sg_init_table(sg_out, 3);
  224. sg_set_buf(&sg_out[0], dst1, *dst1_len);
  225. sg_set_buf(&sg_out[1], dst2, *dst2_len);
  226. sg_set_buf(&sg_out[2], pad, sizeof(pad));
  227. crypto_blkcipher_setkey((void *)tfm, key, key_len);
  228. iv = crypto_blkcipher_crt(tfm)->iv;
  229. ivsize = crypto_blkcipher_ivsize(tfm);
  230. memcpy(iv, aes_iv, ivsize);
  231. /*
  232. print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1,
  233. key, key_len, 1);
  234. print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1,
  235. src, src_len, 1);
  236. */
  237. ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
  238. crypto_free_blkcipher(tfm);
  239. if (ret < 0) {
  240. pr_err("ceph_aes_decrypt failed %d\n", ret);
  241. return ret;
  242. }
  243. if (src_len <= *dst1_len)
  244. last_byte = ((char *)dst1)[src_len - 1];
  245. else if (src_len <= *dst1_len + *dst2_len)
  246. last_byte = ((char *)dst2)[src_len - *dst1_len - 1];
  247. else
  248. last_byte = pad[src_len - *dst1_len - *dst2_len - 1];
  249. if (last_byte <= 16 && src_len >= last_byte) {
  250. src_len -= last_byte;
  251. } else {
  252. pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
  253. last_byte, (int)src_len);
  254. return -EPERM; /* bad padding */
  255. }
  256. if (src_len < *dst1_len) {
  257. *dst1_len = src_len;
  258. *dst2_len = 0;
  259. } else {
  260. *dst2_len = src_len - *dst1_len;
  261. }
  262. /*
  263. print_hex_dump(KERN_ERR, "dec out1: ", DUMP_PREFIX_NONE, 16, 1,
  264. dst1, *dst1_len, 1);
  265. print_hex_dump(KERN_ERR, "dec out2: ", DUMP_PREFIX_NONE, 16, 1,
  266. dst2, *dst2_len, 1);
  267. */
  268. return 0;
  269. }
  270. int ceph_decrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
  271. const void *src, size_t src_len)
  272. {
  273. switch (secret->type) {
  274. case CEPH_CRYPTO_NONE:
  275. if (*dst_len < src_len)
  276. return -ERANGE;
  277. memcpy(dst, src, src_len);
  278. *dst_len = src_len;
  279. return 0;
  280. case CEPH_CRYPTO_AES:
  281. return ceph_aes_decrypt(secret->key, secret->len, dst,
  282. dst_len, src, src_len);
  283. default:
  284. return -EINVAL;
  285. }
  286. }
  287. int ceph_decrypt2(struct ceph_crypto_key *secret,
  288. void *dst1, size_t *dst1_len,
  289. void *dst2, size_t *dst2_len,
  290. const void *src, size_t src_len)
  291. {
  292. size_t t;
  293. switch (secret->type) {
  294. case CEPH_CRYPTO_NONE:
  295. if (*dst1_len + *dst2_len < src_len)
  296. return -ERANGE;
  297. t = min(*dst1_len, src_len);
  298. memcpy(dst1, src, t);
  299. *dst1_len = t;
  300. src += t;
  301. src_len -= t;
  302. if (src_len) {
  303. t = min(*dst2_len, src_len);
  304. memcpy(dst2, src, t);
  305. *dst2_len = t;
  306. }
  307. return 0;
  308. case CEPH_CRYPTO_AES:
  309. return ceph_aes_decrypt2(secret->key, secret->len,
  310. dst1, dst1_len, dst2, dst2_len,
  311. src, src_len);
  312. default:
  313. return -EINVAL;
  314. }
  315. }
  316. int ceph_encrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
  317. const void *src, size_t src_len)
  318. {
  319. switch (secret->type) {
  320. case CEPH_CRYPTO_NONE:
  321. if (*dst_len < src_len)
  322. return -ERANGE;
  323. memcpy(dst, src, src_len);
  324. *dst_len = src_len;
  325. return 0;
  326. case CEPH_CRYPTO_AES:
  327. return ceph_aes_encrypt(secret->key, secret->len, dst,
  328. dst_len, src, src_len);
  329. default:
  330. return -EINVAL;
  331. }
  332. }
  333. int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
  334. const void *src1, size_t src1_len,
  335. const void *src2, size_t src2_len)
  336. {
  337. switch (secret->type) {
  338. case CEPH_CRYPTO_NONE:
  339. if (*dst_len < src1_len + src2_len)
  340. return -ERANGE;
  341. memcpy(dst, src1, src1_len);
  342. memcpy(dst + src1_len, src2, src2_len);
  343. *dst_len = src1_len + src2_len;
  344. return 0;
  345. case CEPH_CRYPTO_AES:
  346. return ceph_aes_encrypt2(secret->key, secret->len, dst, dst_len,
  347. src1, src1_len, src2, src2_len);
  348. default:
  349. return -EINVAL;
  350. }
  351. }