You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

665 lines
15 KiB

  1. /******************************************************
  2. Copyright (c) 2017 Percona LLC and/or its affiliates.
  3. Encryption datasink implementation for XtraBackup.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; version 2 of the License.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  14. *******************************************************/
  15. #include <my_base.h>
  16. #include "common.h"
  17. #include "datasink.h"
  18. #include "xbcrypt.h"
  19. #include "xbcrypt_common.h"
  20. #include "crc_glue.h"
  21. typedef struct {
  22. pthread_t id;
  23. uint num;
  24. pthread_mutex_t ctrl_mutex;
  25. pthread_cond_t ctrl_cond;
  26. pthread_mutex_t data_mutex;
  27. pthread_cond_t data_cond;
  28. my_bool started;
  29. my_bool data_avail;
  30. my_bool cancelled;
  31. my_bool failed;
  32. const uchar *from;
  33. size_t from_len;
  34. uchar *to;
  35. size_t to_len;
  36. size_t to_size;
  37. const uchar *iv;
  38. size_t iv_len;
  39. unsigned long long offset;
  40. my_bool hash_appended;
  41. gcry_cipher_hd_t cipher_handle;
  42. xb_rcrypt_result_t parse_result;
  43. } crypt_thread_ctxt_t;
  44. typedef struct {
  45. crypt_thread_ctxt_t *threads;
  46. uint nthreads;
  47. int encrypt_algo;
  48. size_t chunk_size;
  49. char *encrypt_key;
  50. char *encrypt_key_file;
  51. } ds_decrypt_ctxt_t;
  52. typedef struct {
  53. ds_decrypt_ctxt_t *crypt_ctxt;
  54. size_t bytes_processed;
  55. ds_file_t *dest_file;
  56. uchar *buf;
  57. size_t buf_len;
  58. size_t buf_size;
  59. } ds_decrypt_file_t;
  60. int ds_decrypt_encrypt_threads = 1;
  61. static ds_ctxt_t *decrypt_init(const char *root);
  62. static ds_file_t *decrypt_open(ds_ctxt_t *ctxt, const char *path,
  63. MY_STAT *mystat);
  64. static int decrypt_write(ds_file_t *file, const void *buf, size_t len);
  65. static int decrypt_close(ds_file_t *file);
  66. static void decrypt_deinit(ds_ctxt_t *ctxt);
  67. datasink_t datasink_decrypt = {
  68. &decrypt_init,
  69. &decrypt_open,
  70. &decrypt_write,
  71. &decrypt_close,
  72. &decrypt_deinit
  73. };
  74. static crypt_thread_ctxt_t *create_worker_threads(uint n);
  75. static void destroy_worker_threads(crypt_thread_ctxt_t *threads, uint n);
  76. static void *decrypt_worker_thread_func(void *arg);
  77. static
  78. ds_ctxt_t *
  79. decrypt_init(const char *root)
  80. {
  81. ds_ctxt_t *ctxt;
  82. ds_decrypt_ctxt_t *decrypt_ctxt;
  83. crypt_thread_ctxt_t *threads;
  84. if (xb_crypt_init(NULL)) {
  85. return NULL;
  86. }
  87. /* Create and initialize the worker threads */
  88. threads = create_worker_threads(ds_decrypt_encrypt_threads);
  89. if (threads == NULL) {
  90. msg("decrypt: failed to create worker threads.\n");
  91. return NULL;
  92. }
  93. ctxt = (ds_ctxt_t *) my_malloc(sizeof(ds_ctxt_t) +
  94. sizeof(ds_decrypt_ctxt_t),
  95. MYF(MY_FAE));
  96. decrypt_ctxt = (ds_decrypt_ctxt_t *) (ctxt + 1);
  97. decrypt_ctxt->threads = threads;
  98. decrypt_ctxt->nthreads = ds_decrypt_encrypt_threads;
  99. ctxt->ptr = decrypt_ctxt;
  100. ctxt->root = my_strdup(root, MYF(MY_FAE));
  101. return ctxt;
  102. }
  103. static
  104. ds_file_t *
  105. decrypt_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
  106. {
  107. ds_ctxt_t *dest_ctxt;
  108. ds_decrypt_ctxt_t *crypt_ctxt;
  109. ds_decrypt_file_t *crypt_file;
  110. char new_name[FN_REFLEN];
  111. ds_file_t *file;
  112. xb_ad(ctxt->pipe_ctxt != NULL);
  113. dest_ctxt = ctxt->pipe_ctxt;
  114. crypt_ctxt = (ds_decrypt_ctxt_t *) ctxt->ptr;
  115. file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
  116. sizeof(ds_decrypt_file_t),
  117. MYF(MY_FAE|MY_ZEROFILL));
  118. crypt_file = (ds_decrypt_file_t *) (file + 1);
  119. /* Remove the .xbcrypt extension from the filename */
  120. strncpy(new_name, path, FN_REFLEN);
  121. new_name[strlen(new_name) - 8] = 0;
  122. crypt_file->dest_file = ds_open(dest_ctxt, new_name, mystat);
  123. if (crypt_file->dest_file == NULL) {
  124. msg("decrypt: ds_open(\"%s\") failed.\n", new_name);
  125. goto err;
  126. }
  127. crypt_file->crypt_ctxt = crypt_ctxt;
  128. crypt_file->buf = NULL;
  129. crypt_file->buf_size = 0;
  130. crypt_file->buf_len = 0;
  131. file->ptr = crypt_file;
  132. file->path = crypt_file->dest_file->path;
  133. return file;
  134. err:
  135. if (crypt_file->dest_file) {
  136. ds_close(crypt_file->dest_file);
  137. }
  138. my_free(file);
  139. return NULL;
  140. }
  141. #define CHECK_BUF_SIZE(ptr, size, buf, len) \
  142. if (ptr + size - buf > (ssize_t) len) { \
  143. result = XB_CRYPT_READ_INCOMPLETE; \
  144. goto exit; \
  145. }
  146. static
  147. xb_rcrypt_result_t
  148. parse_xbcrypt_chunk(crypt_thread_ctxt_t *thd, const uchar *buf, size_t len,
  149. size_t *bytes_processed)
  150. {
  151. const uchar *ptr;
  152. uint version;
  153. ulong checksum, checksum_exp;
  154. ulonglong tmp;
  155. xb_rcrypt_result_t result = XB_CRYPT_READ_CHUNK;
  156. *bytes_processed = 0;
  157. ptr = buf;
  158. CHECK_BUF_SIZE(ptr, XB_CRYPT_CHUNK_MAGIC_SIZE, buf, len);
  159. if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC3,
  160. XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
  161. version = 3;
  162. } else if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC2,
  163. XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
  164. version = 2;
  165. } else if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC1,
  166. XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
  167. version = 1;
  168. } else {
  169. msg("%s:%s: wrong chunk magic at offset 0x%llx.\n",
  170. my_progname, __FUNCTION__, thd->offset);
  171. result = XB_CRYPT_READ_ERROR;
  172. goto exit;
  173. }
  174. ptr += XB_CRYPT_CHUNK_MAGIC_SIZE;
  175. thd->offset += XB_CRYPT_CHUNK_MAGIC_SIZE;
  176. CHECK_BUF_SIZE(ptr, 8, buf, len);
  177. tmp = uint8korr(ptr); /* reserved */
  178. ptr += 8;
  179. thd->offset += 8;
  180. CHECK_BUF_SIZE(ptr, 8, buf, len);
  181. tmp = uint8korr(ptr); /* original size */
  182. ptr += 8;
  183. if (tmp > INT_MAX) {
  184. msg("%s:%s: invalid original size at offset 0x%llx.\n",
  185. my_progname, __FUNCTION__, thd->offset);
  186. result = XB_CRYPT_READ_ERROR;
  187. goto exit;
  188. }
  189. thd->offset += 8;
  190. thd->to_len = (size_t)tmp;
  191. if (thd->to_size < thd->to_len + XB_CRYPT_HASH_LEN) {
  192. thd->to = (uchar *) my_realloc(
  193. thd->to,
  194. thd->to_len + XB_CRYPT_HASH_LEN,
  195. MYF(MY_FAE | MY_ALLOW_ZERO_PTR));
  196. thd->to_size = thd->to_len;
  197. }
  198. CHECK_BUF_SIZE(ptr, 8, buf, len);
  199. tmp = uint8korr(ptr); /* encrypted size */
  200. ptr += 8;
  201. if (tmp > INT_MAX) {
  202. msg("%s:%s: invalid encrypted size at offset 0x%llx.\n",
  203. my_progname, __FUNCTION__, thd->offset);
  204. result = XB_CRYPT_READ_ERROR;
  205. goto exit;
  206. }
  207. thd->offset += 8;
  208. thd->from_len = (size_t)tmp;
  209. xb_a(thd->from_len <= thd->to_len + XB_CRYPT_HASH_LEN);
  210. CHECK_BUF_SIZE(ptr, 4, buf, len);
  211. checksum_exp = uint4korr(ptr); /* checksum */
  212. ptr += 4;
  213. thd->offset += 4;
  214. /* iv size */
  215. if (version == 1) {
  216. thd->iv_len = 0;
  217. thd->iv = NULL;
  218. } else {
  219. CHECK_BUF_SIZE(ptr, 8, buf, len);
  220. tmp = uint8korr(ptr);
  221. if (tmp > INT_MAX) {
  222. msg("%s:%s: invalid iv size at offset 0x%llx.\n",
  223. my_progname, __FUNCTION__, thd->offset);
  224. result = XB_CRYPT_READ_ERROR;
  225. goto exit;
  226. }
  227. ptr += 8;
  228. thd->offset += 8;
  229. thd->iv_len = (size_t)tmp;
  230. }
  231. if (thd->iv_len > 0) {
  232. CHECK_BUF_SIZE(ptr, thd->iv_len, buf, len);
  233. thd->iv = ptr;
  234. ptr += thd->iv_len;
  235. }
  236. /* for version euqals 2 we need to read in the iv data but do not init
  237. CTR with it */
  238. if (version == 2) {
  239. thd->iv_len = 0;
  240. thd->iv = 0;
  241. }
  242. if (thd->from_len > 0) {
  243. CHECK_BUF_SIZE(ptr, thd->from_len, buf, len);
  244. thd->from = ptr;
  245. ptr += thd->from_len;
  246. }
  247. xb_ad(thd->from_len <= thd->to_len);
  248. checksum = crc32_iso3309(0, thd->from, thd->from_len);
  249. if (checksum != checksum_exp) {
  250. msg("%s:%s invalid checksum at offset 0x%llx, "
  251. "expected 0x%lx, actual 0x%lx.\n", my_progname,
  252. __FUNCTION__, thd->offset, checksum_exp, checksum);
  253. result = XB_CRYPT_READ_ERROR;
  254. goto exit;
  255. }
  256. thd->offset += thd->from_len;
  257. thd->hash_appended = version > 2;
  258. exit:
  259. *bytes_processed = (size_t) (ptr - buf);
  260. return result;
  261. }
  262. static
  263. int
  264. decrypt_write(ds_file_t *file, const void *buf, size_t len)
  265. {
  266. ds_decrypt_file_t *crypt_file;
  267. ds_decrypt_ctxt_t *crypt_ctxt;
  268. crypt_thread_ctxt_t *threads;
  269. crypt_thread_ctxt_t *thd;
  270. uint nthreads;
  271. uint i;
  272. size_t bytes_processed;
  273. xb_rcrypt_result_t parse_result = XB_CRYPT_READ_CHUNK;
  274. my_bool err = FALSE;
  275. crypt_file = (ds_decrypt_file_t *) file->ptr;
  276. crypt_ctxt = crypt_file->crypt_ctxt;
  277. threads = crypt_ctxt->threads;
  278. nthreads = crypt_ctxt->nthreads;
  279. if (crypt_file->buf_len > 0) {
  280. thd = threads;
  281. pthread_mutex_lock(&thd->ctrl_mutex);
  282. do {
  283. if (parse_result == XB_CRYPT_READ_INCOMPLETE) {
  284. crypt_file->buf_size = crypt_file->buf_size * 2;
  285. crypt_file->buf = (uchar *) my_realloc(
  286. crypt_file->buf,
  287. crypt_file->buf_size,
  288. MYF(MY_FAE|MY_ALLOW_ZERO_PTR));
  289. }
  290. memcpy(crypt_file->buf + crypt_file->buf_len,
  291. buf, MY_MIN(crypt_file->buf_size -
  292. crypt_file->buf_len, len));
  293. parse_result = parse_xbcrypt_chunk(
  294. thd, crypt_file->buf,
  295. crypt_file->buf_size, &bytes_processed);
  296. if (parse_result == XB_CRYPT_READ_ERROR) {
  297. pthread_mutex_unlock(&thd->ctrl_mutex);
  298. return 1;
  299. }
  300. } while (parse_result == XB_CRYPT_READ_INCOMPLETE &&
  301. crypt_file->buf_size < len);
  302. if (parse_result != XB_CRYPT_READ_CHUNK) {
  303. msg("decrypt: incomplete data.\n");
  304. pthread_mutex_unlock(&thd->ctrl_mutex);
  305. return 1;
  306. }
  307. pthread_mutex_lock(&thd->data_mutex);
  308. thd->data_avail = TRUE;
  309. pthread_cond_signal(&thd->data_cond);
  310. pthread_mutex_unlock(&thd->data_mutex);
  311. len -= bytes_processed - crypt_file->buf_len;
  312. buf += bytes_processed - crypt_file->buf_len;
  313. /* reap */
  314. pthread_mutex_lock(&thd->data_mutex);
  315. while (thd->data_avail == TRUE) {
  316. pthread_cond_wait(&thd->data_cond,
  317. &thd->data_mutex);
  318. }
  319. if (thd->failed) {
  320. msg("decrypt: failed to decrypt chunk.\n");
  321. err = TRUE;
  322. }
  323. xb_a(thd->to_len > 0);
  324. if (!err &&
  325. ds_write(crypt_file->dest_file, thd->to, thd->to_len)) {
  326. msg("decrypt: write to destination failed.\n");
  327. err = TRUE;
  328. }
  329. crypt_file->bytes_processed += thd->from_len;
  330. pthread_mutex_unlock(&thd->data_mutex);
  331. pthread_mutex_unlock(&thd->ctrl_mutex);
  332. crypt_file->buf_len = 0;
  333. if (err) {
  334. return 1;
  335. }
  336. }
  337. while (parse_result == XB_CRYPT_READ_CHUNK && len > 0) {
  338. uint max_thread;
  339. for (i = 0; i < nthreads; i++) {
  340. thd = threads + i;
  341. pthread_mutex_lock(&thd->ctrl_mutex);
  342. parse_result = parse_xbcrypt_chunk(
  343. thd, buf, len, &bytes_processed);
  344. if (parse_result == XB_CRYPT_READ_ERROR) {
  345. pthread_mutex_unlock(&thd->ctrl_mutex);
  346. err = TRUE;
  347. break;
  348. }
  349. thd->parse_result = parse_result;
  350. if (parse_result != XB_CRYPT_READ_CHUNK) {
  351. pthread_mutex_unlock(&thd->ctrl_mutex);
  352. break;
  353. }
  354. pthread_mutex_lock(&thd->data_mutex);
  355. thd->data_avail = TRUE;
  356. pthread_cond_signal(&thd->data_cond);
  357. pthread_mutex_unlock(&thd->data_mutex);
  358. len -= bytes_processed;
  359. buf += bytes_processed;
  360. }
  361. max_thread = (i < nthreads) ? i : nthreads - 1;
  362. /* Reap and write decrypted data */
  363. for (i = 0; i <= max_thread; i++) {
  364. thd = threads + i;
  365. if (thd->parse_result != XB_CRYPT_READ_CHUNK) {
  366. break;
  367. }
  368. pthread_mutex_lock(&thd->data_mutex);
  369. while (thd->data_avail == TRUE) {
  370. pthread_cond_wait(&thd->data_cond,
  371. &thd->data_mutex);
  372. }
  373. if (thd->failed) {
  374. msg("decrypt: failed to decrypt chunk.\n");
  375. err = TRUE;
  376. }
  377. xb_a(thd->to_len > 0);
  378. if (!err && ds_write(crypt_file->dest_file, thd->to,
  379. thd->to_len)) {
  380. msg("decrypt: write to destination failed.\n");
  381. err = TRUE;
  382. }
  383. crypt_file->bytes_processed += thd->from_len;
  384. pthread_mutex_unlock(&thd->data_mutex);
  385. pthread_mutex_unlock(&thd->ctrl_mutex);
  386. }
  387. if (err) {
  388. return 1;
  389. }
  390. }
  391. if (parse_result == XB_CRYPT_READ_INCOMPLETE && len > 0) {
  392. crypt_file->buf_len = len;
  393. if (crypt_file->buf_size < len) {
  394. crypt_file->buf = (uchar *) my_realloc(
  395. crypt_file->buf,
  396. crypt_file->buf_len,
  397. MYF(MY_FAE | MY_ALLOW_ZERO_PTR));
  398. crypt_file->buf_size = len;
  399. }
  400. memcpy(crypt_file->buf, buf, len);
  401. }
  402. return 0;
  403. }
  404. static
  405. int
  406. decrypt_close(ds_file_t *file)
  407. {
  408. ds_decrypt_file_t *crypt_file;
  409. ds_file_t *dest_file;
  410. int rc = 0;
  411. crypt_file = (ds_decrypt_file_t *) file->ptr;
  412. dest_file = crypt_file->dest_file;
  413. if (ds_close(dest_file)) {
  414. rc = 1;
  415. }
  416. my_free(crypt_file->buf);
  417. my_free(file);
  418. return rc;
  419. }
  420. static
  421. void
  422. decrypt_deinit(ds_ctxt_t *ctxt)
  423. {
  424. ds_decrypt_ctxt_t *crypt_ctxt;
  425. xb_ad(ctxt->pipe_ctxt != NULL);
  426. crypt_ctxt = (ds_decrypt_ctxt_t *) ctxt->ptr;
  427. destroy_worker_threads(crypt_ctxt->threads, crypt_ctxt->nthreads);
  428. my_free(ctxt->root);
  429. my_free(ctxt);
  430. }
  431. static
  432. crypt_thread_ctxt_t *
  433. create_worker_threads(uint n)
  434. {
  435. crypt_thread_ctxt_t *threads;
  436. uint i;
  437. threads = (crypt_thread_ctxt_t *)
  438. my_malloc(sizeof(crypt_thread_ctxt_t) * n,
  439. MYF(MY_FAE | MY_ZEROFILL));
  440. for (i = 0; i < n; i++) {
  441. crypt_thread_ctxt_t *thd = threads + i;
  442. thd->num = i + 1;
  443. /* Initialize the control mutex and condition var */
  444. if (pthread_mutex_init(&thd->ctrl_mutex, NULL) ||
  445. pthread_cond_init(&thd->ctrl_cond, NULL)) {
  446. goto err;
  447. }
  448. /* Initialize and data mutex and condition var */
  449. if (pthread_mutex_init(&thd->data_mutex, NULL) ||
  450. pthread_cond_init(&thd->data_cond, NULL)) {
  451. goto err;
  452. }
  453. xb_crypt_cipher_open(&thd->cipher_handle);
  454. pthread_mutex_lock(&thd->ctrl_mutex);
  455. if (pthread_create(&thd->id, NULL, decrypt_worker_thread_func,
  456. thd)) {
  457. msg("decrypt: pthread_create() failed: "
  458. "errno = %d\n", errno);
  459. goto err;
  460. }
  461. }
  462. /* Wait for the threads to start */
  463. for (i = 0; i < n; i++) {
  464. crypt_thread_ctxt_t *thd = threads + i;
  465. while (thd->started == FALSE)
  466. pthread_cond_wait(&thd->ctrl_cond, &thd->ctrl_mutex);
  467. pthread_mutex_unlock(&thd->ctrl_mutex);
  468. }
  469. return threads;
  470. err:
  471. return NULL;
  472. }
  473. static
  474. void
  475. destroy_worker_threads(crypt_thread_ctxt_t *threads, uint n)
  476. {
  477. uint i;
  478. for (i = 0; i < n; i++) {
  479. crypt_thread_ctxt_t *thd = threads + i;
  480. pthread_mutex_lock(&thd->data_mutex);
  481. threads[i].cancelled = TRUE;
  482. pthread_cond_signal(&thd->data_cond);
  483. pthread_mutex_unlock(&thd->data_mutex);
  484. pthread_join(thd->id, NULL);
  485. pthread_cond_destroy(&thd->data_cond);
  486. pthread_mutex_destroy(&thd->data_mutex);
  487. pthread_cond_destroy(&thd->ctrl_cond);
  488. pthread_mutex_destroy(&thd->ctrl_mutex);
  489. xb_crypt_cipher_close(thd->cipher_handle);
  490. my_free(thd->to);
  491. }
  492. my_free(threads);
  493. }
  494. static
  495. void *
  496. decrypt_worker_thread_func(void *arg)
  497. {
  498. crypt_thread_ctxt_t *thd = (crypt_thread_ctxt_t *) arg;
  499. pthread_mutex_lock(&thd->ctrl_mutex);
  500. pthread_mutex_lock(&thd->data_mutex);
  501. thd->started = TRUE;
  502. pthread_cond_signal(&thd->ctrl_cond);
  503. pthread_mutex_unlock(&thd->ctrl_mutex);
  504. while (1) {
  505. thd->data_avail = FALSE;
  506. pthread_cond_signal(&thd->data_cond);
  507. while (!thd->data_avail && !thd->cancelled) {
  508. pthread_cond_wait(&thd->data_cond, &thd->data_mutex);
  509. }
  510. if (thd->cancelled)
  511. break;
  512. if (xb_crypt_decrypt(thd->cipher_handle, thd->from,
  513. thd->from_len, thd->to, &thd->to_len,
  514. thd->iv, thd->iv_len,
  515. thd->hash_appended)) {
  516. thd->failed = TRUE;
  517. continue;
  518. }
  519. }
  520. pthread_mutex_unlock(&thd->data_mutex);
  521. return NULL;
  522. }