"Fossies" - the Fresh Open Source Software Archive 
Member "cryptsetup-2.4.3/lib/libdevmapper.c" (13 Jan 2022, 85399 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "libdevmapper.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.4.1_vs_2.4.2.
1 /*
2 * libdevmapper - device-mapper backend for cryptsetup
3 *
4 * Copyright (C) 2004 Jana Saout <jana@saout.de>
5 * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
6 * Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
7 * Copyright (C) 2009-2021 Milan Broz
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #include <stdio.h>
25 #include <stdbool.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <libdevmapper.h>
29 #include <uuid/uuid.h>
30 #include <sys/stat.h>
31 #ifdef HAVE_SYS_SYSMACROS_H
32 # include <sys/sysmacros.h> /* for major, minor */
33 #endif
34 #include <assert.h>
35 #include "internal.h"
36
37 #define DM_CRYPT_TARGET "crypt"
38 #define DM_VERITY_TARGET "verity"
39 #define DM_INTEGRITY_TARGET "integrity"
40 #define DM_LINEAR_TARGET "linear"
41 #define DM_ERROR_TARGET "error"
42 #define DM_ZERO_TARGET "zero"
43 #define RETRY_COUNT 5
44
45 /* Set if DM target versions were probed */
46 static bool _dm_ioctl_checked = false;
47 static bool _dm_crypt_checked = false;
48 static bool _dm_verity_checked = false;
49 static bool _dm_integrity_checked = false;
50
51 static int _quiet_log = 0;
52 static uint32_t _dm_flags = 0;
53
54 static struct crypt_device *_context = NULL;
55 static int _dm_use_count = 0;
56
57 /* Check if we have DM flag to instruct kernel to force wipe buffers */
58 #if !HAVE_DECL_DM_TASK_SECURE_DATA
59 static int dm_task_secure_data(struct dm_task *dmt) { return 1; }
60 #endif
61
62 /* Compatibility for old device-mapper without udev support */
63 #if HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG
64 #define CRYPT_TEMP_UDEV_FLAGS DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG | \
65 DM_UDEV_DISABLE_DISK_RULES_FLAG | \
66 DM_UDEV_DISABLE_OTHER_RULES_FLAG
67 #define _dm_task_set_cookie dm_task_set_cookie
68 #define _dm_udev_wait dm_udev_wait
69 #else
70 #define CRYPT_TEMP_UDEV_FLAGS 0
71 static int _dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { return 0; }
72 static int _dm_udev_wait(uint32_t cookie) { return 0; };
73 #endif
74
75 static int _dm_use_udev(void)
76 {
77 #ifdef USE_UDEV /* cannot be enabled if devmapper is too old */
78 return dm_udev_get_sync_support();
79 #else
80 return 0;
81 #endif
82 }
83
84 __attribute__((format(printf, 4, 5)))
85 static void set_dm_error(int level,
86 const char *file __attribute__((unused)),
87 int line __attribute__((unused)),
88 const char *f, ...)
89 {
90 char *msg = NULL;
91 va_list va;
92
93 va_start(va, f);
94 if (vasprintf(&msg, f, va) > 0) {
95 if (level < 4 && !_quiet_log) {
96 log_err(_context, "%s", msg);
97 } else {
98 /* We do not use DM visual stack backtrace here */
99 if (strncmp(msg, "<backtrace>", 11))
100 log_dbg(_context, "%s", msg);
101 }
102 }
103 free(msg);
104 va_end(va);
105 }
106
107 static int _dm_satisfies_version(unsigned target_maj, unsigned target_min, unsigned target_patch,
108 unsigned actual_maj, unsigned actual_min, unsigned actual_patch)
109 {
110 if (actual_maj > target_maj)
111 return 1;
112
113 if (actual_maj == target_maj && actual_min > target_min)
114 return 1;
115
116 if (actual_maj == target_maj && actual_min == target_min && actual_patch >= target_patch)
117 return 1;
118
119 return 0;
120 }
121
122 static void _dm_set_crypt_compat(struct crypt_device *cd,
123 unsigned crypt_maj,
124 unsigned crypt_min,
125 unsigned crypt_patch)
126 {
127 if (_dm_crypt_checked || crypt_maj == 0)
128 return;
129
130 log_dbg(cd, "Detected dm-crypt version %i.%i.%i.",
131 crypt_maj, crypt_min, crypt_patch);
132
133 if (_dm_satisfies_version(1, 2, 0, crypt_maj, crypt_min, crypt_patch))
134 _dm_flags |= DM_KEY_WIPE_SUPPORTED;
135 else
136 log_dbg(cd, "Suspend and resume disabled, no wipe key support.");
137
138 if (_dm_satisfies_version(1, 10, 0, crypt_maj, crypt_min, crypt_patch))
139 _dm_flags |= DM_LMK_SUPPORTED;
140
141 /* not perfect, 2.6.33 supports with 1.7.0 */
142 if (_dm_satisfies_version(1, 8, 0, crypt_maj, crypt_min, crypt_patch))
143 _dm_flags |= DM_PLAIN64_SUPPORTED;
144
145 if (_dm_satisfies_version(1, 11, 0, crypt_maj, crypt_min, crypt_patch))
146 _dm_flags |= DM_DISCARDS_SUPPORTED;
147
148 if (_dm_satisfies_version(1, 13, 0, crypt_maj, crypt_min, crypt_patch))
149 _dm_flags |= DM_TCW_SUPPORTED;
150
151 if (_dm_satisfies_version(1, 14, 0, crypt_maj, crypt_min, crypt_patch)) {
152 _dm_flags |= DM_SAME_CPU_CRYPT_SUPPORTED;
153 _dm_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED;
154 }
155
156 if (_dm_satisfies_version(1, 18, 1, crypt_maj, crypt_min, crypt_patch))
157 _dm_flags |= DM_KERNEL_KEYRING_SUPPORTED;
158
159 if (_dm_satisfies_version(1, 17, 0, crypt_maj, crypt_min, crypt_patch)) {
160 _dm_flags |= DM_SECTOR_SIZE_SUPPORTED;
161 _dm_flags |= DM_CAPI_STRING_SUPPORTED;
162 }
163
164 if (_dm_satisfies_version(1, 19, 0, crypt_maj, crypt_min, crypt_patch))
165 _dm_flags |= DM_BITLK_EBOIV_SUPPORTED;
166
167 if (_dm_satisfies_version(1, 20, 0, crypt_maj, crypt_min, crypt_patch))
168 _dm_flags |= DM_BITLK_ELEPHANT_SUPPORTED;
169
170 if (_dm_satisfies_version(1, 22, 0, crypt_maj, crypt_min, crypt_patch))
171 _dm_flags |= DM_CRYPT_NO_WORKQUEUE_SUPPORTED;
172
173 _dm_crypt_checked = true;
174 }
175
176 static void _dm_set_verity_compat(struct crypt_device *cd,
177 unsigned verity_maj,
178 unsigned verity_min,
179 unsigned verity_patch)
180 {
181 if (_dm_verity_checked || verity_maj == 0)
182 return;
183
184 log_dbg(cd, "Detected dm-verity version %i.%i.%i.",
185 verity_maj, verity_min, verity_patch);
186
187 _dm_flags |= DM_VERITY_SUPPORTED;
188
189 /*
190 * ignore_corruption, restart_on corruption is available since 1.2 (kernel 4.1)
191 * ignore_zero_blocks since 1.3 (kernel 4.5)
192 * (but some dm-verity targets 1.2 don't support it)
193 * FEC is added in 1.3 as well.
194 * Check at most once is added in 1.4 (kernel 4.17).
195 */
196 if (_dm_satisfies_version(1, 3, 0, verity_maj, verity_min, verity_patch)) {
197 _dm_flags |= DM_VERITY_ON_CORRUPTION_SUPPORTED;
198 _dm_flags |= DM_VERITY_FEC_SUPPORTED;
199 }
200
201 if (_dm_satisfies_version(1, 5, 0, verity_maj, verity_min, verity_patch))
202 _dm_flags |= DM_VERITY_SIGNATURE_SUPPORTED;
203
204 if (_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch))
205 _dm_flags |= DM_VERITY_PANIC_CORRUPTION_SUPPORTED;
206
207 _dm_verity_checked = true;
208 }
209
210 static void _dm_set_integrity_compat(struct crypt_device *cd,
211 unsigned integrity_maj,
212 unsigned integrity_min,
213 unsigned integrity_patch)
214 {
215 if (_dm_integrity_checked || integrity_maj == 0)
216 return;
217
218 log_dbg(cd, "Detected dm-integrity version %i.%i.%i.",
219 integrity_maj, integrity_min, integrity_patch);
220
221 _dm_flags |= DM_INTEGRITY_SUPPORTED;
222
223 if (_dm_satisfies_version(1, 2, 0, integrity_maj, integrity_min, integrity_patch))
224 _dm_flags |= DM_INTEGRITY_RECALC_SUPPORTED;
225
226 if (_dm_satisfies_version(1, 3, 0, integrity_maj, integrity_min, integrity_patch))
227 _dm_flags |= DM_INTEGRITY_BITMAP_SUPPORTED;
228
229 if (_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch))
230 _dm_flags |= DM_INTEGRITY_FIX_PADDING_SUPPORTED;
231
232 if (_dm_satisfies_version(1, 6, 0, integrity_maj, integrity_min, integrity_patch))
233 _dm_flags |= DM_INTEGRITY_DISCARDS_SUPPORTED;
234
235 if (_dm_satisfies_version(1, 7, 0, integrity_maj, integrity_min, integrity_patch))
236 _dm_flags |= DM_INTEGRITY_FIX_HMAC_SUPPORTED;
237
238 if (_dm_satisfies_version(1, 8, 0, integrity_maj, integrity_min, integrity_patch))
239 _dm_flags |= DM_INTEGRITY_RESET_RECALC_SUPPORTED;
240
241 _dm_integrity_checked = true;
242 }
243
244 /* We use this for loading target module */
245 static void _dm_check_target(dm_target_type target_type)
246 {
247 #if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION
248 struct dm_task *dmt;
249 const char *target_name = NULL;
250
251 if (!(_dm_flags & DM_GET_TARGET_VERSION_SUPPORTED))
252 return;
253
254 if (target_type == DM_CRYPT)
255 target_name = DM_CRYPT_TARGET;
256 else if (target_type == DM_VERITY)
257 target_name = DM_VERITY_TARGET;
258 else if (target_type == DM_INTEGRITY)
259 target_name = DM_INTEGRITY_TARGET;
260 else
261 return;
262
263 if (!(dmt = dm_task_create(DM_DEVICE_GET_TARGET_VERSION)))
264 return;
265
266 if (dm_task_set_name(dmt, target_name))
267 dm_task_run(dmt);
268
269 dm_task_destroy(dmt);
270 #endif
271 }
272
273 static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_type)
274 {
275 struct dm_task *dmt;
276 struct dm_versions *target, *last_target;
277 char dm_version[16];
278 unsigned dm_maj, dm_min, dm_patch;
279 int r = 0;
280
281 if ((target_type == DM_CRYPT && _dm_crypt_checked) ||
282 (target_type == DM_VERITY && _dm_verity_checked) ||
283 (target_type == DM_INTEGRITY && _dm_integrity_checked) ||
284 (target_type == DM_LINEAR) || (target_type == DM_ZERO) ||
285 (_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked))
286 return 1;
287
288 /* Shut up DM while checking */
289 _quiet_log = 1;
290
291 _dm_check_target(target_type);
292
293 if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
294 goto out;
295
296 if (!dm_task_run(dmt))
297 goto out;
298
299 if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version)))
300 goto out;
301
302 if (!_dm_ioctl_checked) {
303 if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3)
304 goto out;
305 log_dbg(cd, "Detected dm-ioctl version %u.%u.%u.", dm_maj, dm_min, dm_patch);
306
307 if (_dm_satisfies_version(4, 20, 0, dm_maj, dm_min, dm_patch))
308 _dm_flags |= DM_SECURE_SUPPORTED;
309 #if HAVE_DECL_DM_TASK_DEFERRED_REMOVE
310 if (_dm_satisfies_version(4, 27, 0, dm_maj, dm_min, dm_patch))
311 _dm_flags |= DM_DEFERRED_SUPPORTED;
312 #endif
313 #if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION
314 if (_dm_satisfies_version(4, 41, 0, dm_maj, dm_min, dm_patch))
315 _dm_flags |= DM_GET_TARGET_VERSION_SUPPORTED;
316 #endif
317 }
318
319 target = dm_task_get_versions(dmt);
320 do {
321 last_target = target;
322 if (!strcmp(DM_CRYPT_TARGET, target->name)) {
323 _dm_set_crypt_compat(cd, (unsigned)target->version[0],
324 (unsigned)target->version[1],
325 (unsigned)target->version[2]);
326 } else if (!strcmp(DM_VERITY_TARGET, target->name)) {
327 _dm_set_verity_compat(cd, (unsigned)target->version[0],
328 (unsigned)target->version[1],
329 (unsigned)target->version[2]);
330 } else if (!strcmp(DM_INTEGRITY_TARGET, target->name)) {
331 _dm_set_integrity_compat(cd, (unsigned)target->version[0],
332 (unsigned)target->version[1],
333 (unsigned)target->version[2]);
334 }
335 target = (struct dm_versions *)((char *) target + target->next);
336 } while (last_target != target);
337
338 r = 1;
339 if (!_dm_ioctl_checked)
340 log_dbg(cd, "Device-mapper backend running with UDEV support %sabled.",
341 _dm_use_udev() ? "en" : "dis");
342
343 _dm_ioctl_checked = true;
344 out:
345 if (dmt)
346 dm_task_destroy(dmt);
347
348 _quiet_log = 0;
349 return r;
350 }
351
352 int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags)
353 {
354 _dm_check_versions(cd, target);
355 *flags = _dm_flags;
356
357 if (target == DM_UNKNOWN &&
358 _dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked)
359 return 0;
360
361 if ((target == DM_CRYPT && _dm_crypt_checked) ||
362 (target == DM_VERITY && _dm_verity_checked) ||
363 (target == DM_INTEGRITY && _dm_integrity_checked) ||
364 (target == DM_LINEAR) || (target == DM_ZERO)) /* nothing to check */
365 return 0;
366
367 return -ENODEV;
368 }
369
370 /* This doesn't run any kernel checks, just set up userspace libdevmapper */
371 void dm_backend_init(struct crypt_device *cd)
372 {
373 if (!_dm_use_count++) {
374 log_dbg(cd, "Initialising device-mapper backend library.");
375 dm_log_init(set_dm_error);
376 dm_log_init_verbose(10);
377 }
378 }
379
380 void dm_backend_exit(struct crypt_device *cd)
381 {
382 if (_dm_use_count && (!--_dm_use_count)) {
383 log_dbg(cd, "Releasing device-mapper backend.");
384 dm_log_init_verbose(0);
385 dm_log_init(NULL);
386 dm_lib_release();
387 }
388 }
389
390 /* libdevmapper is not context friendly, switch context on every DM call. */
391 static int dm_init_context(struct crypt_device *cd, dm_target_type target)
392 {
393 _context = cd;
394 if (!_dm_check_versions(cd, target)) {
395 if (getuid() || geteuid())
396 log_err(cd, _("Cannot initialize device-mapper, "
397 "running as non-root user."));
398 else
399 log_err(cd, _("Cannot initialize device-mapper. "
400 "Is dm_mod kernel module loaded?"));
401 _context = NULL;
402 return -ENOTSUP;
403 }
404 return 0;
405 }
406 static void dm_exit_context(void)
407 {
408 _context = NULL;
409 }
410
411 /* Return path to DM device */
412 char *dm_device_path(const char *prefix, int major, int minor)
413 {
414 struct dm_task *dmt;
415 const char *name;
416 char path[PATH_MAX];
417
418 if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
419 return NULL;
420 if (!dm_task_set_minor(dmt, minor) ||
421 !dm_task_set_major(dmt, major) ||
422 !dm_task_no_flush(dmt) ||
423 !dm_task_run(dmt) ||
424 !(name = dm_task_get_name(dmt))) {
425 dm_task_destroy(dmt);
426 return NULL;
427 }
428
429 if (snprintf(path, sizeof(path), "%s%s", prefix ?: "", name) < 0)
430 path[0] = '\0';
431
432 dm_task_destroy(dmt);
433
434 return strdup(path);
435 }
436
437 char *dm_device_name(const char *path)
438 {
439 struct stat st;
440
441 if (stat(path, &st) < 0 || !S_ISBLK(st.st_mode))
442 return NULL;
443
444 return dm_device_path(NULL, major(st.st_rdev), minor(st.st_rdev));
445 }
446
447 static void hex_key(char *hexkey, size_t key_size, const char *key)
448 {
449 unsigned i;
450
451 for(i = 0; i < key_size; i++)
452 sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
453 }
454
455 static size_t int_log10(uint64_t x)
456 {
457 uint64_t r = 0;
458 for (x /= 10; x > 0; x /= 10)
459 r++;
460 return r;
461 }
462
463 #define CLEN 64 /* 2*MAX_CIPHER_LEN */
464 #define CLENS "63" /* for sscanf length + '\0' */
465 #define CAPIL 144 /* should be enough to fit whole capi string */
466 #define CAPIS "143" /* for sscanf of crypto API string + 16 + \0 */
467
468 static int cipher_c2dm(const char *org_c, const char *org_i, unsigned tag_size,
469 char *c_dm, int c_dm_size,
470 char *i_dm, int i_dm_size)
471 {
472 int c_size = 0, i_size = 0, i;
473 char cipher[CLEN], mode[CLEN], iv[CLEN+1], tmp[CLEN];
474 char capi[CAPIL];
475
476 if (!c_dm || !c_dm_size || !i_dm || !i_dm_size)
477 return -EINVAL;
478
479 i = sscanf(org_c, "%" CLENS "[^-]-%" CLENS "s", cipher, tmp);
480 if (i != 2)
481 return -EINVAL;
482
483 i = sscanf(tmp, "%" CLENS "[^-]-%" CLENS "s", mode, iv);
484 if (i == 1) {
485 memset(iv, 0, sizeof(iv));
486 strncpy(iv, mode, sizeof(iv)-1);
487 *mode = '\0';
488 if (snprintf(capi, sizeof(capi), "%s", cipher) < 0)
489 return -EINVAL;
490 } else if (i == 2) {
491 if (snprintf(capi, sizeof(capi), "%s(%s)", mode, cipher) < 0)
492 return -EINVAL;
493 } else
494 return -EINVAL;
495
496 if (!org_i) {
497 /* legacy mode: CIPHER-MODE-IV*/
498 i_size = snprintf(i_dm, i_dm_size, "%s", "");
499 c_size = snprintf(c_dm, c_dm_size, "%s", org_c);
500 } else if (!strcmp(org_i, "none")) {
501 /* IV only: capi:MODE(CIPHER)-IV */
502 i_size = snprintf(i_dm, i_dm_size, " integrity:%u:none", tag_size);
503 c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv);
504 } else if (!strcmp(org_i, "aead") && !strcmp(mode, "ccm")) {
505 /* CCM AEAD: capi:rfc4309(MODE(CIPHER))-IV */
506 i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
507 c_size = snprintf(c_dm, c_dm_size, "capi:rfc4309(%s)-%s", capi, iv);
508 } else if (!strcmp(org_i, "aead")) {
509 /* AEAD: capi:MODE(CIPHER))-IV */
510 i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
511 c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv);
512 } else if (!strcmp(org_i, "poly1305")) {
513 /* POLY1305 AEAD: capi:rfc7539(MODE(CIPHER),POLY1305)-IV */
514 i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
515 c_size = snprintf(c_dm, c_dm_size, "capi:rfc7539(%s,poly1305)-%s", capi, iv);
516 } else {
517 /* other AEAD: capi:authenc(<AUTH>,MODE(CIPHER))-IV */
518 i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
519 c_size = snprintf(c_dm, c_dm_size, "capi:authenc(%s,%s)-%s", org_i, capi, iv);
520 }
521
522 if (c_size < 0 || c_size == c_dm_size)
523 return -EINVAL;
524 if (i_size < 0 || i_size == i_dm_size)
525 return -EINVAL;
526
527 return 0;
528 }
529
530 static int cipher_dm2c(char **org_c, char **org_i, const char *c_dm, const char *i_dm)
531 {
532 char cipher[CLEN], mode[CLEN], iv[CLEN], auth[CLEN];
533 char tmp[CAPIL], dmcrypt_tmp[CAPIL*2], capi[CAPIL+1];
534 size_t len;
535 int i;
536
537 if (!c_dm)
538 return -EINVAL;
539
540 /* legacy mode */
541 if (strncmp(c_dm, "capi:", 4)) {
542 if (!(*org_c = strdup(c_dm)))
543 return -ENOMEM;
544 *org_i = NULL;
545 return 0;
546 }
547
548 /* modes with capi: prefix */
549 i = sscanf(c_dm, "capi:%" CAPIS "[^-]-%" CLENS "s", tmp, iv);
550 if (i != 2)
551 return -EINVAL;
552
553 len = strlen(tmp);
554 if (len < 2)
555 return -EINVAL;
556
557 if (tmp[len-1] == ')')
558 tmp[len-1] = '\0';
559
560 if (sscanf(tmp, "rfc4309(%" CAPIS "s", capi) == 1) {
561 if (!(*org_i = strdup("aead")))
562 return -ENOMEM;
563 } else if (sscanf(tmp, "rfc7539(%" CAPIS "[^,],%" CLENS "s", capi, auth) == 2) {
564 if (!(*org_i = strdup(auth)))
565 return -ENOMEM;
566 } else if (sscanf(tmp, "authenc(%" CLENS "[^,],%" CAPIS "s", auth, capi) == 2) {
567 if (!(*org_i = strdup(auth)))
568 return -ENOMEM;
569 } else {
570 if (i_dm) {
571 if (!(*org_i = strdup(i_dm)))
572 return -ENOMEM;
573 } else
574 *org_i = NULL;
575 memset(capi, 0, sizeof(capi));
576 strncpy(capi, tmp, sizeof(capi)-1);
577 }
578
579 i = sscanf(capi, "%" CLENS "[^(](%" CLENS "[^)])", mode, cipher);
580 if (i == 2)
581 i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv);
582 else
583 i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv);
584 if (i < 0 || (size_t)i >= sizeof(dmcrypt_tmp)) {
585 free(*org_i);
586 *org_i = NULL;
587 return -EINVAL;
588 }
589
590 if (!(*org_c = strdup(dmcrypt_tmp))) {
591 free(*org_i);
592 *org_i = NULL;
593 return -ENOMEM;
594 }
595
596 return 0;
597 }
598
599 static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u)
600 {
601 size_t r = snprintf(buf, buf_size, " %s:%u", s, u);
602 assert(r > 0 && r < buf_size);
603 return buf;
604 }
605
606 /* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */
607 static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
608 {
609 int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0;
610 char *params = NULL, *hexkey = NULL;
611 char sector_feature[32], features[512], integrity_dm[256], cipher_dm[256];
612
613 if (!tgt)
614 return NULL;
615
616 r = cipher_c2dm(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size,
617 cipher_dm, sizeof(cipher_dm), integrity_dm, sizeof(integrity_dm));
618 if (r < 0)
619 return NULL;
620
621 if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
622 num_options++;
623 if (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT)
624 num_options++;
625 if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
626 num_options++;
627 if (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE)
628 num_options++;
629 if (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)
630 num_options++;
631 if (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS)
632 num_options++;
633 if (tgt->u.crypt.integrity)
634 num_options++;
635 if (tgt->u.crypt.sector_size != SECTOR_SIZE)
636 num_options++;
637
638 if (num_options) { /* MAX length int32 + 15 + 15 + 23 + 18 + 19 + 17 + 13 + int32 + integrity_str */
639 r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s%s", num_options,
640 (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "",
641 (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "",
642 (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "",
643 (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE) ? " no_read_workqueue" : "",
644 (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) ? " no_write_workqueue" : "",
645 (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) ? " iv_large_sectors" : "",
646 (tgt->u.crypt.sector_size != SECTOR_SIZE) ?
647 _uf(sector_feature, sizeof(sector_feature), "sector_size", tgt->u.crypt.sector_size) : "",
648 integrity_dm);
649 if (r < 0 || (size_t)r >= sizeof(features))
650 goto out;
651 } else
652 *features = '\0';
653
654 if (crypt_is_cipher_null(cipher_dm))
655 null_cipher = 1;
656
657 if (null_cipher)
658 hexkey = crypt_safe_alloc(2);
659 else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
660 keystr_len = strlen(tgt->u.crypt.vk->key_description) + int_log10(tgt->u.crypt.vk->keylength) + 10;
661 hexkey = crypt_safe_alloc(keystr_len);
662 } else
663 hexkey = crypt_safe_alloc(tgt->u.crypt.vk->keylength * 2 + 1);
664
665 if (!hexkey)
666 goto out;
667
668 if (null_cipher)
669 strncpy(hexkey, "-", 2);
670 else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
671 r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description);
672 if (r < 0 || r >= keystr_len)
673 goto out;
674 } else
675 hex_key(hexkey, tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key);
676
677 max_size = strlen(hexkey) + strlen(cipher_dm) +
678 strlen(device_block_path(tgt->data_device)) +
679 strlen(features) + 64;
680 params = crypt_safe_alloc(max_size);
681 if (!params)
682 goto out;
683
684 r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s",
685 cipher_dm, hexkey, tgt->u.crypt.iv_offset,
686 device_block_path(tgt->data_device), tgt->u.crypt.offset,
687 features);
688 if (r < 0 || r >= max_size) {
689 crypt_safe_free(params);
690 params = NULL;
691 }
692 out:
693 crypt_safe_free(hexkey);
694 return params;
695 }
696
697 /* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */
698 static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
699 {
700 int max_size, max_fec_size, max_verify_size, r, num_options = 0;
701 struct crypt_params_verity *vp;
702 char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
703 char features[256], *fec_features = NULL, *verity_verify_args = NULL;
704
705 if (!tgt || !tgt->u.verity.vp)
706 return NULL;
707
708 vp = tgt->u.verity.vp;
709
710 /* These flags are not compatible */
711 if ((flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) &&
712 (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION))
713 flags &= ~CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
714 if ((flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) &&
715 (flags & (CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)))
716 flags &= ~CRYPT_ACTIVATE_IGNORE_CORRUPTION;
717
718 if (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION)
719 num_options++;
720 if (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION)
721 num_options++;
722 if (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)
723 num_options++;
724 if (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS)
725 num_options++;
726 if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE)
727 num_options++;
728
729 max_fec_size = (tgt->u.verity.fec_device ? strlen(device_block_path(tgt->u.verity.fec_device)) : 0) + 256;
730 fec_features = crypt_safe_alloc(max_fec_size);
731 if (!fec_features)
732 goto out;
733
734 if (tgt->u.verity.fec_device) { /* MAX length 21 + path + 11 + int64 + 12 + int64 + 11 + int32 */
735 num_options += 8;
736 r = snprintf(fec_features, max_fec_size,
737 " use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 " fec_roots %" PRIu32,
738 device_block_path(tgt->u.verity.fec_device), tgt->u.verity.fec_offset,
739 tgt->u.verity.fec_blocks, vp->fec_roots);
740 if (r < 0 || r >= max_fec_size)
741 goto out;
742 } else
743 *fec_features = '\0';
744
745 max_verify_size = (tgt->u.verity.root_hash_sig_key_desc ? strlen(tgt->u.verity.root_hash_sig_key_desc) : 0) + 32;
746 verity_verify_args = crypt_safe_alloc(max_verify_size);
747 if (!verity_verify_args)
748 goto out;
749 if (tgt->u.verity.root_hash_sig_key_desc) { /* MAX length 24 + key_str */
750 num_options += 2;
751 r = snprintf(verity_verify_args, max_verify_size,
752 " root_hash_sig_key_desc %s", tgt->u.verity.root_hash_sig_key_desc);
753 if (r < 0 || r >= max_verify_size)
754 goto out;
755 } else
756 *verity_verify_args = '\0';
757
758 if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 */
759 r = snprintf(features, sizeof(features), " %d%s%s%s%s%s", num_options,
760 (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "",
761 (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "",
762 (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? " panic_on_corruption" : "",
763 (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "",
764 (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "");
765 if (r < 0 || (size_t)r >= sizeof(features))
766 goto out;
767 } else
768 *features = '\0';
769
770 hexroot = crypt_safe_alloc(tgt->u.verity.root_hash_size * 2 + 1);
771 if (!hexroot)
772 goto out;
773 hex_key(hexroot, tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
774
775 hexsalt = crypt_safe_alloc(vp->salt_size ? vp->salt_size * 2 + 1 : 2);
776 if (!hexsalt)
777 goto out;
778 if (vp->salt_size)
779 hex_key(hexsalt, vp->salt_size, vp->salt);
780 else
781 strncpy(hexsalt, "-", 2);
782
783 max_size = strlen(hexroot) + strlen(hexsalt) +
784 strlen(device_block_path(tgt->data_device)) +
785 strlen(device_block_path(tgt->u.verity.hash_device)) +
786 strlen(vp->hash_name) + strlen(features) + strlen(fec_features) + 128 +
787 strlen(verity_verify_args);
788
789 params = crypt_safe_alloc(max_size);
790 if (!params)
791 goto out;
792
793 r = snprintf(params, max_size,
794 "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s%s%s%s",
795 vp->hash_type, device_block_path(tgt->data_device),
796 device_block_path(tgt->u.verity.hash_device),
797 vp->data_block_size, vp->hash_block_size,
798 vp->data_size, tgt->u.verity.hash_offset,
799 vp->hash_name, hexroot, hexsalt, features, fec_features,
800 verity_verify_args);
801 if (r < 0 || r >= max_size) {
802 crypt_safe_free(params);
803 params = NULL;
804 }
805 out:
806 crypt_safe_free(fec_features);
807 crypt_safe_free(verity_verify_args);
808 crypt_safe_free(hexroot);
809 crypt_safe_free(hexsalt);
810 return params;
811 }
812
813 static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags)
814 {
815 int r, max_size, max_integrity, max_journal_integrity, max_journal_crypt, num_options = 0;
816 char *params_out = NULL, *params, *hexkey, mode, feature[6][32];
817 char *features, *integrity, *journal_integrity, *journal_crypt;
818
819 if (!tgt)
820 return NULL;
821
822 max_integrity = (tgt->u.integrity.integrity && tgt->u.integrity.vk ? tgt->u.integrity.vk->keylength * 2 : 0) +
823 (tgt->u.integrity.integrity ? strlen(tgt->u.integrity.integrity) : 0) + 32;
824 max_journal_integrity = (tgt->u.integrity.journal_integrity && tgt->u.integrity.journal_integrity_key ?
825 tgt->u.integrity.journal_integrity_key->keylength * 2 : 0) +
826 (tgt->u.integrity.journal_integrity ? strlen(tgt->u.integrity.journal_integrity) : 0) + 32;
827 max_journal_crypt = (tgt->u.integrity.journal_crypt && tgt->u.integrity.journal_crypt_key ?
828 tgt->u.integrity.journal_crypt_key->keylength * 2 : 0) +
829 (tgt->u.integrity.journal_crypt ? strlen(tgt->u.integrity.journal_crypt) : 0) + 32;
830 max_size = strlen(device_block_path(tgt->data_device)) +
831 (tgt->u.integrity.meta_device ? strlen(device_block_path(tgt->u.integrity.meta_device)) : 0) +
832 max_integrity + max_journal_integrity + max_journal_crypt + 512;
833
834 params = crypt_safe_alloc(max_size);
835 features = crypt_safe_alloc(max_size);
836 integrity = crypt_safe_alloc(max_integrity);
837 journal_integrity = crypt_safe_alloc(max_journal_integrity);
838 journal_crypt = crypt_safe_alloc(max_journal_crypt);
839 if (!params || !features || !integrity || !journal_integrity || !journal_crypt)
840 goto out;
841
842 if (tgt->u.integrity.integrity) { /* MAX length 16 + str_integrity + str_key */
843 num_options++;
844
845 if (tgt->u.integrity.vk) {
846 hexkey = crypt_safe_alloc(tgt->u.integrity.vk->keylength * 2 + 1);
847 if (!hexkey)
848 goto out;
849 hex_key(hexkey, tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
850 } else
851 hexkey = NULL;
852
853 r = snprintf(integrity, max_integrity, " internal_hash:%s%s%s",
854 tgt->u.integrity.integrity, hexkey ? ":" : "", hexkey ?: "");
855 crypt_safe_free(hexkey);
856 if (r < 0 || r >= max_integrity)
857 goto out;
858 }
859
860 if (tgt->u.integrity.journal_integrity) { /* MAX length 14 + str_journal_integrity + str_key */
861 num_options++;
862
863 if (tgt->u.integrity.journal_integrity_key) {
864 hexkey = crypt_safe_alloc(tgt->u.integrity.journal_integrity_key->keylength * 2 + 1);
865 if (!hexkey)
866 goto out;
867 hex_key(hexkey, tgt->u.integrity.journal_integrity_key->keylength,
868 tgt->u.integrity.journal_integrity_key->key);
869 } else
870 hexkey = NULL;
871
872 r = snprintf(journal_integrity, max_journal_integrity, " journal_mac:%s%s%s",
873 tgt->u.integrity.journal_integrity, hexkey ? ":" : "", hexkey ?: "");
874 crypt_safe_free(hexkey);
875 if (r < 0 || r >= max_journal_integrity)
876 goto out;
877 }
878
879 if (tgt->u.integrity.journal_crypt) { /* MAX length 15 + str_journal_crypt + str_key */
880 num_options++;
881
882 if (tgt->u.integrity.journal_crypt_key) {
883 hexkey = crypt_safe_alloc(tgt->u.integrity.journal_crypt_key->keylength * 2 + 1);
884 if (!hexkey)
885 goto out;
886 hex_key(hexkey, tgt->u.integrity.journal_crypt_key->keylength,
887 tgt->u.integrity.journal_crypt_key->key);
888 } else
889 hexkey = NULL;
890
891 r = snprintf(journal_crypt, max_journal_crypt, " journal_crypt:%s%s%s",
892 tgt->u.integrity.journal_crypt, hexkey ? ":" : "", hexkey ?: "");
893 crypt_safe_free(hexkey);
894 if (r < 0 || r >= max_journal_crypt)
895 goto out;
896 }
897
898 if (tgt->u.integrity.journal_size)
899 num_options++;
900 if (tgt->u.integrity.journal_watermark)
901 num_options++;
902 if (tgt->u.integrity.journal_commit_time)
903 num_options++;
904 if (tgt->u.integrity.interleave_sectors)
905 num_options++;
906 if (tgt->u.integrity.sector_size)
907 num_options++;
908 if (tgt->u.integrity.buffer_sectors)
909 num_options++;
910 if (tgt->u.integrity.fix_padding)
911 num_options++;
912 if (tgt->u.integrity.fix_hmac)
913 num_options++;
914 if (tgt->u.integrity.legacy_recalc)
915 num_options++;
916 if (tgt->u.integrity.meta_device)
917 num_options++;
918 if (flags & CRYPT_ACTIVATE_RECALCULATE)
919 num_options++;
920 if (flags & CRYPT_ACTIVATE_RECALCULATE_RESET)
921 num_options++;
922 if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
923 num_options++;
924
925 r = snprintf(features, max_size, "%d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", num_options,
926 tgt->u.integrity.journal_size ? _uf(feature[0], sizeof(feature[0]), /* MAX length 17 + int32 */
927 "journal_sectors", (unsigned)(tgt->u.integrity.journal_size / SECTOR_SIZE)) : "",
928 tgt->u.integrity.journal_watermark ? _uf(feature[1], sizeof(feature[1]), /* MAX length 19 + int32 */
929 /* bitmap overloaded values */
930 (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "sectors_per_bit" : "journal_watermark",
931 tgt->u.integrity.journal_watermark) : "",
932 tgt->u.integrity.journal_commit_time ? _uf(feature[2], sizeof(feature[2]), /* MAX length 23 + int32 */
933 /* bitmap overloaded values */
934 (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "bitmap_flush_interval" : "commit_time",
935 tgt->u.integrity.journal_commit_time) : "",
936 tgt->u.integrity.interleave_sectors ? _uf(feature[3], sizeof(feature[3]), /* MAX length 20 + int32 */
937 "interleave_sectors", tgt->u.integrity.interleave_sectors) : "",
938 tgt->u.integrity.sector_size ? _uf(feature[4], sizeof(feature[4]), /* MAX length 12 + int32 */
939 "block_size", tgt->u.integrity.sector_size) : "",
940 tgt->u.integrity.buffer_sectors ? _uf(feature[5], sizeof(feature[5]), /* MAX length 16 + int32 */
941 "buffer_sectors", tgt->u.integrity.buffer_sectors) : "",
942 tgt->u.integrity.integrity ? integrity : "",
943 tgt->u.integrity.journal_integrity ? journal_integrity : "",
944 tgt->u.integrity.journal_crypt ? journal_crypt : "",
945 tgt->u.integrity.fix_padding ? " fix_padding" : "", /* MAX length 12 */
946 tgt->u.integrity.fix_hmac ? " fix_hmac" : "", /* MAX length 9 */
947 tgt->u.integrity.legacy_recalc ? " legacy_recalculate" : "", /* MAX length 19 */
948 flags & CRYPT_ACTIVATE_RECALCULATE ? " recalculate" : "", /* MAX length 12 */
949 flags & CRYPT_ACTIVATE_RECALCULATE_RESET ? " reset_recalculate" : "", /* MAX length 18 */
950 flags & CRYPT_ACTIVATE_ALLOW_DISCARDS ? " allow_discards" : "", /* MAX length 15 */
951 tgt->u.integrity.meta_device ? " meta_device:" : "", /* MAX length 13 + str_device */
952 tgt->u.integrity.meta_device ? device_block_path(tgt->u.integrity.meta_device) : "");
953 if (r < 0 || r >= max_size)
954 goto out;
955
956 if (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP)
957 mode = 'B';
958 else if (flags & CRYPT_ACTIVATE_RECOVERY)
959 mode = 'R';
960 else if (flags & CRYPT_ACTIVATE_NO_JOURNAL)
961 mode = 'D';
962 else
963 mode = 'J';
964
965 r = snprintf(params, max_size, "%s %" PRIu64 " %d %c %s",
966 device_block_path(tgt->data_device), tgt->u.integrity.offset,
967 tgt->u.integrity.tag_size, mode, features);
968 if (r < 0 || r >= max_size)
969 goto out;
970
971 params_out = params;
972 out:
973 crypt_safe_free(features);
974 crypt_safe_free(integrity);
975 crypt_safe_free(journal_integrity);
976 crypt_safe_free(journal_crypt);
977 if (!params_out)
978 crypt_safe_free(params);
979
980 return params_out;
981 }
982
983 static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags __attribute__((unused)))
984 {
985 char *params;
986 int r;
987 int max_size = strlen(device_block_path(tgt->data_device)) + int_log10(tgt->u.linear.offset) + 3;
988
989 params = crypt_safe_alloc(max_size);
990 if (!params)
991 return NULL;
992
993 r = snprintf(params, max_size, "%s %" PRIu64,
994 device_block_path(tgt->data_device), tgt->u.linear.offset);
995
996 if (r < 0 || r >= max_size) {
997 crypt_safe_free(params);
998 params = NULL;
999 }
1000
1001 return params;
1002 }
1003
1004 static char *get_dm_zero_params(const struct dm_target *tgt __attribute__((unused)), uint32_t flags __attribute__((unused)))
1005 {
1006 char *params = crypt_safe_alloc(1);
1007 if (!params)
1008 return NULL;
1009
1010 params[0] = 0;
1011 return params;
1012 }
1013
1014 /* DM helpers */
1015 static int _dm_remove(const char *name, int udev_wait, int deferred)
1016 {
1017 int r = 0;
1018 struct dm_task *dmt;
1019 uint32_t cookie = 0;
1020
1021 if (!_dm_use_udev())
1022 udev_wait = 0;
1023
1024 if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
1025 return 0;
1026
1027 if (!dm_task_set_name(dmt, name))
1028 goto out;
1029
1030 #if HAVE_DECL_DM_TASK_RETRY_REMOVE
1031 if (!dm_task_retry_remove(dmt))
1032 goto out;
1033 #endif
1034 #if HAVE_DECL_DM_TASK_DEFERRED_REMOVE
1035 if (deferred && !dm_task_deferred_remove(dmt))
1036 goto out;
1037 #endif
1038 if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK))
1039 goto out;
1040
1041 r = dm_task_run(dmt);
1042
1043 if (udev_wait)
1044 (void)_dm_udev_wait(cookie);
1045 out:
1046 dm_task_destroy(dmt);
1047 return r;
1048 }
1049
1050 static int _dm_simple(int task, const char *name, uint32_t dmflags)
1051 {
1052 int r = 0;
1053 struct dm_task *dmt;
1054
1055 if (!(dmt = dm_task_create(task)))
1056 return 0;
1057
1058 if (name && !dm_task_set_name(dmt, name))
1059 goto out;
1060
1061 if (task == DM_DEVICE_SUSPEND &&
1062 (dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt))
1063 goto out;
1064
1065 if (task == DM_DEVICE_SUSPEND &&
1066 (dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt))
1067 goto out;
1068
1069 r = dm_task_run(dmt);
1070 out:
1071 dm_task_destroy(dmt);
1072 return r;
1073 }
1074
1075 static int _dm_resume_device(const char *name, uint32_t flags);
1076
1077 static int _error_device(const char *name, size_t size)
1078 {
1079 struct dm_task *dmt;
1080 int r = 0;
1081
1082 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
1083 return 0;
1084
1085 if (!dm_task_set_name(dmt, name))
1086 goto out;
1087
1088 if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
1089 goto out;
1090
1091 if (!dm_task_set_ro(dmt))
1092 goto out;
1093
1094 if (!dm_task_no_open_count(dmt))
1095 goto out;
1096
1097 if (!dm_task_run(dmt))
1098 goto out;
1099
1100 if (_dm_resume_device(name, 0)) {
1101 _dm_simple(DM_DEVICE_CLEAR, name, 0);
1102 goto out;
1103 }
1104
1105 r = 1;
1106 out:
1107 dm_task_destroy(dmt);
1108 return r;
1109 }
1110
1111 int dm_error_device(struct crypt_device *cd, const char *name)
1112 {
1113 int r;
1114 struct crypt_dm_active_device dmd;
1115
1116 if (!name)
1117 return -EINVAL;
1118
1119 if (dm_init_context(cd, DM_UNKNOWN))
1120 return -ENOTSUP;
1121
1122 if ((dm_query_device(cd, name, 0, &dmd) >= 0) && _error_device(name, dmd.size))
1123 r = 0;
1124 else
1125 r = -EINVAL;
1126
1127 dm_targets_free(cd, &dmd);
1128
1129 dm_exit_context();
1130
1131 return r;
1132 }
1133
1134 int dm_clear_device(struct crypt_device *cd, const char *name)
1135 {
1136 int r;
1137
1138 if (!name)
1139 return -EINVAL;
1140
1141 if (dm_init_context(cd, DM_UNKNOWN))
1142 return -ENOTSUP;
1143
1144 if (_dm_simple(DM_DEVICE_CLEAR, name, 0))
1145 r = 0;
1146 else
1147 r = -EINVAL;
1148
1149 dm_exit_context();
1150
1151 return r;
1152 }
1153
1154 int dm_remove_device(struct crypt_device *cd, const char *name, uint32_t flags)
1155 {
1156 struct crypt_dm_active_device dmd = {};
1157 int r = -EINVAL;
1158 int retries = (flags & CRYPT_DEACTIVATE_FORCE) ? RETRY_COUNT : 1;
1159 int deferred = (flags & CRYPT_DEACTIVATE_DEFERRED) ? 1 : 0;
1160 int error_target = 0;
1161 uint32_t dmt_flags;
1162
1163 if (!name)
1164 return -EINVAL;
1165
1166 if (dm_init_context(cd, DM_UNKNOWN))
1167 return -ENOTSUP;
1168
1169 if (deferred && !dm_flags(cd, DM_UNKNOWN, &dmt_flags) && !(dmt_flags & DM_DEFERRED_SUPPORTED)) {
1170 log_err(cd, _("Requested deferred flag is not supported."));
1171 dm_exit_context();
1172 return -ENOTSUP;
1173 }
1174
1175 do {
1176 r = _dm_remove(name, 1, deferred) ? 0 : -EINVAL;
1177 if (--retries && r) {
1178 log_dbg(cd, "WARNING: other process locked internal device %s, %s.",
1179 name, retries ? "retrying remove" : "giving up");
1180 sleep(1);
1181 if ((flags & CRYPT_DEACTIVATE_FORCE) && !error_target) {
1182 /* If force flag is set, replace device with error, read-only target.
1183 * it should stop processes from reading it and also removed underlying
1184 * device from mapping, so it is usable again.
1185 * Anyway, if some process try to read temporary cryptsetup device,
1186 * it is bug - no other process should try touch it (e.g. udev).
1187 */
1188 if (!dm_query_device(cd, name, 0, &dmd)) {
1189 _error_device(name, dmd.size);
1190 error_target = 1;
1191 }
1192 }
1193 }
1194 } while (r == -EINVAL && retries);
1195
1196 dm_task_update_nodes();
1197 dm_exit_context();
1198
1199 return r;
1200 }
1201
1202 #define UUID_LEN 37 /* 36 + \0, libuuid ... */
1203 /*
1204 * UUID has format: CRYPT-<devicetype>-[<uuid>-]<device name>
1205 * CRYPT-PLAIN-name
1206 * CRYPT-LUKS1-00000000000000000000000000000000-name
1207 * CRYPT-TEMP-name
1208 */
1209 static int dm_prepare_uuid(struct crypt_device *cd, const char *name, const char *type,
1210 const char *uuid, char *buf, size_t buflen)
1211 {
1212 char *ptr, uuid2[UUID_LEN] = {0};
1213 uuid_t uu;
1214 int i = 0;
1215
1216 /* Remove '-' chars */
1217 if (uuid) {
1218 if (uuid_parse(uuid, uu) < 0) {
1219 log_dbg(cd, "Requested UUID %s has invalid format.", uuid);
1220 return 0;
1221 }
1222
1223 for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
1224 if (uuid[i] != '-') {
1225 *ptr = uuid[i];
1226 ptr++;
1227 }
1228 }
1229
1230 i = snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s%s",
1231 type ?: "", type ? "-" : "",
1232 uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
1233 name);
1234 if (i < 0)
1235 return 0;
1236
1237 log_dbg(cd, "DM-UUID is %s", buf);
1238 if ((size_t)i >= buflen)
1239 log_err(cd, _("DM-UUID for device %s was truncated."), name);
1240
1241 return 1;
1242 }
1243
1244 int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type)
1245 {
1246 int r_udev, r;
1247 char *c;
1248 char dev_uuid[DM_UUID_LEN + DM_BY_ID_PREFIX_LEN] = DM_BY_ID_PREFIX;
1249
1250 if (!dm_prepare_uuid(cd, "", type, uuid, dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN))
1251 return -EINVAL;
1252
1253 c = strrchr(dev_uuid, '-');
1254 if (!c)
1255 return -EINVAL;
1256
1257 /* cut of dm name */
1258 *c = '\0';
1259
1260 /* Either udev or sysfs can report that device is active. */
1261 r = lookup_by_disk_id(dev_uuid);
1262 if (r > 0)
1263 return r;
1264
1265 r_udev = r;
1266 if (r_udev <= 0)
1267 r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
1268
1269 return r == -ENOENT ? r_udev : r;
1270 }
1271
1272 static int _add_dm_targets(struct dm_task *dmt, struct crypt_dm_active_device *dmd)
1273 {
1274 const char *target;
1275 struct dm_target *tgt = &dmd->segment;
1276
1277 do {
1278 switch (tgt->type) {
1279 case DM_CRYPT:
1280 target = DM_CRYPT_TARGET;
1281 break;
1282 case DM_VERITY:
1283 target = DM_VERITY_TARGET;
1284 break;
1285 case DM_INTEGRITY:
1286 target = DM_INTEGRITY_TARGET;
1287 break;
1288 case DM_LINEAR:
1289 target = DM_LINEAR_TARGET;
1290 break;
1291 case DM_ZERO:
1292 target = DM_ZERO_TARGET;
1293 break;
1294 default:
1295 return -ENOTSUP;
1296 }
1297
1298 if (!dm_task_add_target(dmt, tgt->offset, tgt->size, target, tgt->params))
1299 return -EINVAL;
1300
1301 tgt = tgt->next;
1302 } while (tgt);
1303
1304 return 0;
1305 }
1306
1307 static void _destroy_dm_targets_params(struct crypt_dm_active_device *dmd)
1308 {
1309 struct dm_target *t = &dmd->segment;
1310
1311 do {
1312 crypt_safe_free(t->params);
1313 t->params = NULL;
1314 t = t->next;
1315 } while (t);
1316 }
1317
1318 static int _create_dm_targets_params(struct crypt_dm_active_device *dmd)
1319 {
1320 int r;
1321 struct dm_target *tgt = &dmd->segment;
1322
1323 do {
1324 if (tgt->type == DM_CRYPT)
1325 tgt->params = get_dm_crypt_params(tgt, dmd->flags);
1326 else if (tgt->type == DM_VERITY)
1327 tgt->params = get_dm_verity_params(tgt, dmd->flags);
1328 else if (tgt->type == DM_INTEGRITY)
1329 tgt->params = get_dm_integrity_params(tgt, dmd->flags);
1330 else if (tgt->type == DM_LINEAR)
1331 tgt->params = get_dm_linear_params(tgt, dmd->flags);
1332 else if (tgt->type == DM_ZERO)
1333 tgt->params = get_dm_zero_params(tgt, dmd->flags);
1334 else {
1335 r = -ENOTSUP;
1336 goto err;
1337 }
1338
1339 if (!tgt->params) {
1340 r = -EINVAL;
1341 goto err;
1342 }
1343 tgt = tgt->next;
1344 } while (tgt);
1345
1346 return 0;
1347 err:
1348 _destroy_dm_targets_params(dmd);
1349 return r;
1350 }
1351
1352 static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
1353 struct crypt_dm_active_device *dmd)
1354 {
1355 struct dm_task *dmt = NULL;
1356 struct dm_info dmi;
1357 char dev_uuid[DM_UUID_LEN] = {0};
1358 int r = -EINVAL;
1359 uint32_t cookie = 0, read_ahead = 0;
1360 uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
1361
1362 if (dmd->flags & CRYPT_ACTIVATE_PRIVATE)
1363 udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
1364
1365 /* All devices must have DM_UUID, only resize on old device is exception */
1366 if (!dm_prepare_uuid(cd, name, type, dmd->uuid, dev_uuid, sizeof(dev_uuid)))
1367 goto out;
1368
1369 if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
1370 goto out;
1371
1372 if (!dm_task_set_name(dmt, name))
1373 goto out;
1374
1375 if (!dm_task_set_uuid(dmt, dev_uuid))
1376 goto out;
1377
1378 if (!dm_task_secure_data(dmt))
1379 goto out;
1380 if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
1381 goto out;
1382
1383 r = _create_dm_targets_params(dmd);
1384 if (r)
1385 goto out;
1386
1387 r = _add_dm_targets(dmt, dmd);
1388 if (r)
1389 goto out;
1390
1391 r = -EINVAL;
1392
1393 #ifdef DM_READ_AHEAD_MINIMUM_FLAG
1394 if (device_read_ahead(dmd->segment.data_device, &read_ahead) &&
1395 !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
1396 goto out;
1397 #endif
1398 if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
1399 goto out;
1400
1401 if (!dm_task_run(dmt)) {
1402 r = dm_status_device(cd, name);;
1403 if (r >= 0)
1404 r = -EEXIST;
1405 if (r != -EEXIST && r != -ENODEV)
1406 r = -EINVAL;
1407 goto out;
1408 }
1409
1410 if (dm_task_get_info(dmt, &dmi))
1411 r = 0;
1412
1413 if (_dm_use_udev()) {
1414 (void)_dm_udev_wait(cookie);
1415 cookie = 0;
1416 }
1417
1418 if (r < 0)
1419 _dm_remove(name, 1, 0);
1420
1421 out:
1422 if (cookie && _dm_use_udev())
1423 (void)_dm_udev_wait(cookie);
1424
1425 if (dmt)
1426 dm_task_destroy(dmt);
1427
1428 dm_task_update_nodes();
1429
1430 /* If code just loaded target module, update versions */
1431 _dm_check_versions(cd, dmd->segment.type);
1432
1433 _destroy_dm_targets_params(dmd);
1434
1435 return r;
1436 }
1437
1438 static int _dm_resume_device(const char *name, uint32_t dmflags)
1439 {
1440 struct dm_task *dmt;
1441 int r = -EINVAL;
1442 uint32_t cookie = 0;
1443 uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
1444
1445 if (dmflags & DM_RESUME_PRIVATE)
1446 udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
1447
1448 if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
1449 return r;
1450
1451 if (!dm_task_set_name(dmt, name))
1452 goto out;
1453
1454 if ((dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt))
1455 goto out;
1456
1457 if ((dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt))
1458 goto out;
1459
1460 if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
1461 goto out;
1462
1463 if (dm_task_run(dmt))
1464 r = 0;
1465 out:
1466 if (cookie && _dm_use_udev())
1467 (void)_dm_udev_wait(cookie);
1468
1469 dm_task_destroy(dmt);
1470
1471 dm_task_update_nodes();
1472
1473 return r;
1474 }
1475
1476 static int _dm_reload_device(struct crypt_device *cd, const char *name,
1477 struct crypt_dm_active_device *dmd)
1478 {
1479 int r = -EINVAL;
1480 struct dm_task *dmt = NULL;
1481 uint32_t read_ahead = 0;
1482
1483 /* All devices must have DM_UUID, only resize on old device is exception */
1484 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
1485 goto out;
1486
1487 if (!dm_task_set_name(dmt, name))
1488 goto out;
1489
1490 if (!dm_task_secure_data(dmt))
1491 goto out;
1492 if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
1493 goto out;
1494
1495 r = _create_dm_targets_params(dmd);
1496 if (r)
1497 goto out;
1498
1499 r = _add_dm_targets(dmt, dmd);
1500 if (r)
1501 goto out;
1502
1503 r = -EINVAL;
1504
1505 #ifdef DM_READ_AHEAD_MINIMUM_FLAG
1506 if (device_read_ahead(dmd->segment.data_device, &read_ahead) &&
1507 !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
1508 goto out;
1509 #endif
1510
1511 if (dm_task_run(dmt))
1512 r = 0;
1513 out:
1514 if (dmt)
1515 dm_task_destroy(dmt);
1516
1517 /* If code just loaded target module, update versions */
1518 _dm_check_versions(cd, dmd->segment.type);
1519
1520 _destroy_dm_targets_params(dmd);
1521
1522 return r;
1523 }
1524
1525 static void crypt_free_verity_params(struct crypt_params_verity *vp)
1526 {
1527 if (!vp)
1528 return;
1529
1530 free(CONST_CAST(void*)vp->hash_name);
1531 free(CONST_CAST(void*)vp->data_device);
1532 free(CONST_CAST(void*)vp->hash_device);
1533 free(CONST_CAST(void*)vp->fec_device);
1534 free(CONST_CAST(void*)vp->salt);
1535 free(vp);
1536 }
1537
1538 static void _dm_target_free_query_path(struct crypt_device *cd, struct dm_target *tgt)
1539 {
1540 switch(tgt->type) {
1541 case DM_CRYPT:
1542 crypt_free_volume_key(tgt->u.crypt.vk);
1543 free(CONST_CAST(void*)tgt->u.crypt.cipher);
1544 break;
1545 case DM_INTEGRITY:
1546 free(CONST_CAST(void*)tgt->u.integrity.integrity);
1547 crypt_free_volume_key(tgt->u.integrity.vk);
1548
1549 free(CONST_CAST(void*)tgt->u.integrity.journal_integrity);
1550 crypt_free_volume_key(tgt->u.integrity.journal_integrity_key);
1551
1552 free(CONST_CAST(void*)tgt->u.integrity.journal_crypt);
1553 crypt_free_volume_key(tgt->u.integrity.journal_crypt_key);
1554
1555 device_free(cd, tgt->u.integrity.meta_device);
1556 break;
1557 case DM_VERITY:
1558 crypt_free_verity_params(tgt->u.verity.vp);
1559 device_free(cd, tgt->u.verity.hash_device);
1560 free(CONST_CAST(void*)tgt->u.verity.root_hash);
1561 free(CONST_CAST(void*)tgt->u.verity.root_hash_sig_key_desc);
1562 /* fall through */
1563 case DM_LINEAR:
1564 /* fall through */
1565 case DM_ERROR:
1566 /* fall through */
1567 case DM_ZERO:
1568 break;
1569 default:
1570 log_err(cd, _("Unknown dm target type."));
1571 return;
1572 }
1573
1574 device_free(cd, tgt->data_device);
1575 }
1576
1577 static void _dm_target_erase(struct crypt_device *cd, struct dm_target *tgt)
1578 {
1579 if (tgt->direction == TARGET_QUERY)
1580 _dm_target_free_query_path(cd, tgt);
1581
1582 if (tgt->type == DM_CRYPT)
1583 free(CONST_CAST(void*)tgt->u.crypt.integrity);
1584 }
1585
1586 void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd)
1587 {
1588 struct dm_target *t = &dmd->segment, *next = t->next;
1589
1590 _dm_target_erase(cd, t);
1591
1592 while (next) {
1593 t = next;
1594 next = t->next;
1595 _dm_target_erase(cd, t);
1596 free(t);
1597 }
1598
1599 memset(&dmd->segment, 0, sizeof(dmd->segment));
1600 }
1601
1602 int dm_targets_allocate(struct dm_target *first, unsigned count)
1603 {
1604 if (!first || first->next || !count)
1605 return -EINVAL;
1606
1607 while (--count) {
1608 first->next = crypt_zalloc(sizeof(*first));
1609 if (!first->next)
1610 return -ENOMEM;
1611 first = first->next;
1612 }
1613
1614 return 0;
1615 }
1616
1617 static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dmt_flags)
1618 {
1619 int ret = 0;
1620
1621 /* If discard not supported try to load without discard */
1622 if ((*dmd_flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1623 !(dmt_flags & DM_DISCARDS_SUPPORTED)) {
1624 log_dbg(cd, "Discard/TRIM is not supported");
1625 *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS;
1626 ret = 1;
1627 }
1628
1629 /* If kernel keyring is not supported load key directly in dm-crypt */
1630 if ((*dmd_flags & CRYPT_ACTIVATE_KEYRING_KEY) &&
1631 !(dmt_flags & DM_KERNEL_KEYRING_SUPPORTED)) {
1632 log_dbg(cd, "dm-crypt does not support kernel keyring");
1633 *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_KEYRING_KEY;
1634 ret = 1;
1635 }
1636
1637 /* Drop performance options if not supported */
1638 if ((*dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
1639 !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) {
1640 log_dbg(cd, "dm-crypt does not support performance options");
1641 *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS);
1642 ret = 1;
1643 }
1644
1645 /* Drop no workqueue options if not supported */
1646 if ((*dmd_flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
1647 !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
1648 log_dbg(cd, "dm-crypt does not support performance options");
1649 *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE);
1650 ret = 1;
1651 }
1652
1653 return ret;
1654 }
1655
1656 int dm_create_device(struct crypt_device *cd, const char *name,
1657 const char *type,
1658 struct crypt_dm_active_device *dmd)
1659 {
1660 uint32_t dmt_flags = 0;
1661 int r = -EINVAL;
1662
1663 if (!type || !dmd)
1664 return -EINVAL;
1665
1666 if (dm_init_context(cd, dmd->segment.type))
1667 return -ENOTSUP;
1668
1669 r = _dm_create_device(cd, name, type, dmd);
1670
1671 if (r < 0 && dm_flags(cd, dmd->segment.type, &dmt_flags))
1672 goto out;
1673
1674 if (r && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
1675 check_retry(cd, &dmd->flags, dmt_flags)) {
1676 log_dbg(cd, "Retrying open without incompatible options.");
1677 r = _dm_create_device(cd, name, type, dmd);
1678 }
1679
1680 /*
1681 * Print warning if activating dm-crypt cipher_null device unless it's reencryption helper or
1682 * keyslot encryption helper device (LUKS1 cipher_null devices).
1683 */
1684 if (!r && !(dmd->flags & CRYPT_ACTIVATE_PRIVATE) && single_segment(dmd) && dmd->segment.type == DM_CRYPT &&
1685 crypt_is_cipher_null(dmd->segment.u.crypt.cipher))
1686 log_dbg(cd, "Activated dm-crypt device with cipher_null. Device is not encrypted.");
1687
1688 if (r == -EINVAL &&
1689 dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
1690 !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
1691 log_err(cd, _("Requested dm-crypt performance options are not supported."));
1692
1693 if (r == -EINVAL &&
1694 dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) &&
1695 !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
1696 log_err(cd, _("Requested dm-crypt performance options are not supported."));
1697
1698 if (r == -EINVAL && dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
1699 CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
1700 CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
1701 CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) &&
1702 !(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED))
1703 log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
1704
1705 if (r == -EINVAL && dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION &&
1706 !(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED))
1707 log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
1708
1709 if (r == -EINVAL && dmd->segment.type == DM_VERITY &&
1710 dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED))
1711 log_err(cd, _("Requested dm-verity FEC options are not supported."));
1712
1713 if (r == -EINVAL && dmd->segment.type == DM_CRYPT) {
1714 if (dmd->segment.u.crypt.integrity && !(dmt_flags & DM_INTEGRITY_SUPPORTED))
1715 log_err(cd, _("Requested data integrity options are not supported."));
1716 if (dmd->segment.u.crypt.sector_size != SECTOR_SIZE && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED))
1717 log_err(cd, _("Requested sector_size option is not supported."));
1718 }
1719
1720 if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
1721 !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED))
1722 log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
1723
1724 if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE_RESET) &&
1725 !(dmt_flags & DM_INTEGRITY_RESET_RECALC_SUPPORTED))
1726 log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
1727
1728 if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1729 !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
1730 log_err(cd, _("Discard/TRIM is not supported."));
1731
1732 if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) &&
1733 !(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED))
1734 log_err(cd, _("Requested dm-integrity bitmap mode is not supported."));
1735 out:
1736 dm_exit_context();
1737 return r;
1738 }
1739
1740 int dm_reload_device(struct crypt_device *cd, const char *name,
1741 struct crypt_dm_active_device *dmd, uint32_t dmflags, unsigned resume)
1742 {
1743 int r;
1744 uint32_t dmt_flags;
1745
1746 if (!dmd)
1747 return -EINVAL;
1748
1749 if (dm_init_context(cd, dmd->segment.type))
1750 return -ENOTSUP;
1751
1752 if (dm_flags(cd, DM_INTEGRITY, &dmt_flags) || !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED))
1753 dmd->flags &= ~CRYPT_ACTIVATE_RECALCULATE;
1754
1755 r = _dm_reload_device(cd, name, dmd);
1756
1757 if (r == -EINVAL && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR)) {
1758 if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
1759 !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
1760 log_err(cd, _("Requested dm-crypt performance options are not supported."));
1761 if ((dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
1762 !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
1763 log_err(cd, _("Requested dm-crypt performance options are not supported."));
1764 if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1765 !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED))
1766 log_err(cd, _("Discard/TRIM is not supported."));
1767 if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1768 !dm_flags(cd, DM_INTEGRITY, &dmt_flags) && !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
1769 log_err(cd, _("Discard/TRIM is not supported."));
1770 }
1771
1772 if (!r && resume)
1773 r = _dm_resume_device(name, dmflags | act2dmflags(dmd->flags));
1774
1775 dm_exit_context();
1776 return r;
1777 }
1778
1779 static int dm_status_dmi(const char *name, struct dm_info *dmi,
1780 const char *target, char **status_line)
1781 {
1782 struct dm_task *dmt;
1783 uint64_t start, length;
1784 char *target_type, *params = NULL;
1785 int r = -EINVAL;
1786
1787 if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
1788 return r;
1789
1790 if (!dm_task_no_flush(dmt))
1791 goto out;
1792
1793 if (!dm_task_set_name(dmt, name))
1794 goto out;
1795
1796 if (!dm_task_run(dmt))
1797 goto out;
1798
1799 if (!dm_task_get_info(dmt, dmi))
1800 goto out;
1801
1802 if (!dmi->exists) {
1803 r = -ENODEV;
1804 goto out;
1805 }
1806
1807 r = -EEXIST;
1808 dm_get_next_target(dmt, NULL, &start, &length,
1809 &target_type, ¶ms);
1810
1811 if (!target_type || start != 0)
1812 goto out;
1813
1814 if (target && strcmp(target_type, target))
1815 goto out;
1816
1817 /* for target == NULL check all supported */
1818 if (!target && (strcmp(target_type, DM_CRYPT_TARGET) &&
1819 strcmp(target_type, DM_VERITY_TARGET) &&
1820 strcmp(target_type, DM_INTEGRITY_TARGET) &&
1821 strcmp(target_type, DM_LINEAR_TARGET) &&
1822 strcmp(target_type, DM_ZERO_TARGET) &&
1823 strcmp(target_type, DM_ERROR_TARGET)))
1824 goto out;
1825 r = 0;
1826 out:
1827 if (!r && status_line && !(*status_line = strdup(params)))
1828 r = -ENOMEM;
1829
1830 dm_task_destroy(dmt);
1831
1832 return r;
1833 }
1834
1835 int dm_status_device(struct crypt_device *cd, const char *name)
1836 {
1837 int r;
1838 struct dm_info dmi;
1839 struct stat st;
1840
1841 /* libdevmapper is too clever and handles
1842 * path argument differently with error.
1843 * Fail early here if parameter is non-existent path.
1844 */
1845 if (strchr(name, '/') && stat(name, &st) < 0)
1846 return -ENODEV;
1847
1848 if (dm_init_context(cd, DM_UNKNOWN))
1849 return -ENOTSUP;
1850 r = dm_status_dmi(name, &dmi, NULL, NULL);
1851 dm_exit_context();
1852
1853 if (r < 0)
1854 return r;
1855
1856 return (dmi.open_count > 0) ? 1 : 0;
1857 }
1858
1859 int dm_status_suspended(struct crypt_device *cd, const char *name)
1860 {
1861 int r;
1862 struct dm_info dmi;
1863
1864 if (dm_init_context(cd, DM_UNKNOWN))
1865 return -ENOTSUP;
1866 r = dm_status_dmi(name, &dmi, NULL, NULL);
1867 dm_exit_context();
1868
1869 if (r < 0)
1870 return r;
1871
1872 return dmi.suspended ? 1 : 0;
1873 }
1874
1875 static int _dm_status_verity_ok(struct crypt_device *cd, const char *name)
1876 {
1877 int r;
1878 struct dm_info dmi;
1879 char *status_line = NULL;
1880
1881 r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
1882 if (r < 0 || !status_line) {
1883 free(status_line);
1884 return r;
1885 }
1886
1887 log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
1888 r = status_line[0] == 'V' ? 1 : 0;
1889 free(status_line);
1890
1891 return r;
1892 }
1893
1894 int dm_status_verity_ok(struct crypt_device *cd, const char *name)
1895 {
1896 int r;
1897
1898 if (dm_init_context(cd, DM_VERITY))
1899 return -ENOTSUP;
1900 r = _dm_status_verity_ok(cd, name);
1901 dm_exit_context();
1902 return r;
1903 }
1904
1905 int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count)
1906 {
1907 int r;
1908 struct dm_info dmi;
1909 char *status_line = NULL;
1910
1911 if (dm_init_context(cd, DM_INTEGRITY))
1912 return -ENOTSUP;
1913
1914 r = dm_status_dmi(name, &dmi, DM_INTEGRITY_TARGET, &status_line);
1915 if (r < 0 || !status_line) {
1916 free(status_line);
1917 dm_exit_context();
1918 return r;
1919 }
1920
1921 log_dbg(cd, "Integrity volume %s failure status is %s.", name, status_line ?: "");
1922 *count = strtoull(status_line, NULL, 10);
1923 free(status_line);
1924 dm_exit_context();
1925
1926 return 0;
1927 }
1928
1929 /* FIXME use hex wrapper, user val wrappers for line parsing */
1930 static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags,
1931 char *params, struct dm_target *tgt,
1932 uint32_t *act_flags)
1933 {
1934 uint64_t val64;
1935 char *rcipher, *rintegrity, *key_, *rdevice, *endp, buffer[3], *arg, *key_desc;
1936 unsigned int i, val;
1937 int r;
1938 size_t key_size;
1939 struct device *data_device = NULL;
1940 char *cipher = NULL, *integrity = NULL;
1941 struct volume_key *vk = NULL;
1942
1943 tgt->type = DM_CRYPT;
1944 tgt->direction = TARGET_QUERY;
1945 tgt->u.crypt.sector_size = SECTOR_SIZE;
1946
1947 r = -EINVAL;
1948
1949 rcipher = strsep(¶ms, " ");
1950 rintegrity = NULL;
1951
1952 /* skip */
1953 key_ = strsep(¶ms, " ");
1954 if (!params)
1955 goto err;
1956 val64 = strtoull(params, ¶ms, 10);
1957 if (*params != ' ')
1958 goto err;
1959 params++;
1960
1961 tgt->u.crypt.iv_offset = val64;
1962
1963 /* device */
1964 rdevice = strsep(¶ms, " ");
1965 if (get_flags & DM_ACTIVE_DEVICE) {
1966 arg = crypt_lookup_dev(rdevice);
1967 r = device_alloc(cd, &data_device, arg);
1968 free(arg);
1969 if (r < 0 && r != -ENOTBLK)
1970 goto err;
1971 }
1972
1973 r = -EINVAL;
1974
1975 /*offset */
1976 if (!params)
1977 goto err;
1978 val64 = strtoull(params, ¶ms, 10);
1979 tgt->u.crypt.offset = val64;
1980
1981 tgt->u.crypt.tag_size = 0;
1982
1983 /* Features section, available since crypt target version 1.11 */
1984 if (*params) {
1985 if (*params != ' ')
1986 goto err;
1987 params++;
1988
1989 /* Number of arguments */
1990 val64 = strtoull(params, ¶ms, 10);
1991 if (*params != ' ')
1992 goto err;
1993 params++;
1994
1995 for (i = 0; i < val64; i++) {
1996 if (!params)
1997 goto err;
1998 arg = strsep(¶ms, " ");
1999 if (!strcasecmp(arg, "allow_discards"))
2000 *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
2001 else if (!strcasecmp(arg, "same_cpu_crypt"))
2002 *act_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
2003 else if (!strcasecmp(arg, "submit_from_crypt_cpus"))
2004 *act_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
2005 else if (!strcasecmp(arg, "no_read_workqueue"))
2006 *act_flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
2007 else if (!strcasecmp(arg, "no_write_workqueue"))
2008 *act_flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
2009 else if (!strcasecmp(arg, "iv_large_sectors"))
2010 *act_flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
2011 else if (sscanf(arg, "integrity:%u:", &val) == 1) {
2012 tgt->u.crypt.tag_size = val;
2013 rintegrity = strchr(arg + strlen("integrity:"), ':');
2014 if (!rintegrity)
2015 goto err;
2016 rintegrity++;
2017 } else if (sscanf(arg, "sector_size:%u", &val) == 1) {
2018 tgt->u.crypt.sector_size = val;
2019 } else /* unknown option */
2020 goto err;
2021 }
2022
2023 /* All parameters should be processed */
2024 if (params)
2025 goto err;
2026 }
2027
2028 /* cipher */
2029 if (get_flags & DM_ACTIVE_CRYPT_CIPHER) {
2030 r = cipher_dm2c(CONST_CAST(char**)&cipher,
2031 CONST_CAST(char**)&integrity,
2032 rcipher, rintegrity);
2033 if (r < 0)
2034 goto err;
2035 }
2036
2037 r = -EINVAL;
2038
2039 if (key_[0] == ':')
2040 *act_flags |= CRYPT_ACTIVATE_KEYRING_KEY;
2041
2042 if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
2043 /* we will trust kernel the key_string is in expected format */
2044 if (key_[0] == ':') {
2045 if (sscanf(key_ + 1, "%zu", &key_size) != 1)
2046 goto err;
2047 } else
2048 key_size = strlen(key_) / 2;
2049
2050 vk = crypt_alloc_volume_key(key_size, NULL);
2051 if (!vk) {
2052 r = -ENOMEM;
2053 goto err;
2054 }
2055
2056 if (get_flags & DM_ACTIVE_CRYPT_KEY) {
2057 if (key_[0] == ':') {
2058 /* :<key_size>:<key_type>:<key_description> */
2059 key_desc = NULL;
2060 endp = strpbrk(key_ + 1, ":");
2061 if (endp)
2062 key_desc = strpbrk(endp + 1, ":");
2063 if (!key_desc) {
2064 r = -ENOMEM;
2065 goto err;
2066 }
2067 key_desc++;
2068 crypt_volume_key_set_description(vk, key_desc);
2069 } else {
2070 buffer[2] = '\0';
2071 for(i = 0; i < vk->keylength; i++) {
2072 memcpy(buffer, &key_[i * 2], 2);
2073 vk->key[i] = strtoul(buffer, &endp, 16);
2074 if (endp != &buffer[2]) {
2075 r = -EINVAL;
2076 goto err;
2077 }
2078 }
2079 }
2080 }
2081 }
2082 memset(key_, 0, strlen(key_));
2083
2084 if (cipher)
2085 tgt->u.crypt.cipher = cipher;
2086 if (integrity)
2087 tgt->u.crypt.integrity = integrity;
2088 if (data_device)
2089 tgt->data_device = data_device;
2090 if (vk)
2091 tgt->u.crypt.vk = vk;
2092 return 0;
2093 err:
2094 free(cipher);
2095 free(integrity);
2096 device_free(cd, data_device);
2097 crypt_free_volume_key(vk);
2098 return r;
2099 }
2100
2101 static int _dm_target_query_verity(struct crypt_device *cd,
2102 uint32_t get_flags,
2103 char *params,
2104 struct dm_target *tgt,
2105 uint32_t *act_flags)
2106 {
2107 struct crypt_params_verity *vp = NULL;
2108 uint32_t val32;
2109 uint64_t val64;
2110 ssize_t len;
2111 char *str, *str2, *arg;
2112 unsigned int i, features;
2113 int r;
2114 struct device *data_device = NULL, *hash_device = NULL, *fec_device = NULL;
2115 char *hash_name = NULL, *root_hash = NULL, *salt = NULL, *fec_dev_str = NULL;
2116 char *root_hash_sig_key_desc = NULL;
2117
2118 if (get_flags & DM_ACTIVE_VERITY_PARAMS) {
2119 vp = crypt_zalloc(sizeof(*vp));
2120 if (!vp)
2121 return -ENOMEM;
2122 }
2123
2124 tgt->type = DM_VERITY;
2125 tgt->direction = TARGET_QUERY;
2126 tgt->u.verity.vp = vp;
2127
2128 /* version */
2129 val32 = strtoul(params, ¶ms, 10);
2130 if (*params != ' ')
2131 return -EINVAL;
2132 if (vp)
2133 vp->hash_type = val32;
2134 params++;
2135
2136 /* data device */
2137 str = strsep(¶ms, " ");
2138 if (!params)
2139 return -EINVAL;
2140 if (get_flags & DM_ACTIVE_DEVICE) {
2141 str2 = crypt_lookup_dev(str);
2142 r = device_alloc(cd, &data_device, str2);
2143 free(str2);
2144 if (r < 0 && r != -ENOTBLK)
2145 return r;
2146 }
2147
2148 r = -EINVAL;
2149
2150 /* hash device */
2151 str = strsep(¶ms, " ");
2152 if (!params)
2153 goto err;
2154 if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
2155 str2 = crypt_lookup_dev(str);
2156 r = device_alloc(cd, &hash_device, str2);
2157 free(str2);
2158 if (r < 0 && r != -ENOTBLK)
2159 goto err;
2160 }
2161
2162 r = -EINVAL;
2163
2164 /* data block size*/
2165 val32 = strtoul(params, ¶ms, 10);
2166 if (*params != ' ')
2167 goto err;
2168 if (vp)
2169 vp->data_block_size = val32;
2170 params++;
2171
2172 /* hash block size */
2173 val32 = strtoul(params, ¶ms, 10);
2174 if (*params != ' ')
2175 goto err;
2176 if (vp)
2177 vp->hash_block_size = val32;
2178 params++;
2179
2180 /* data blocks */
2181 val64 = strtoull(params, ¶ms, 10);
2182 if (*params != ' ')
2183 goto err;
2184 if (vp)
2185 vp->data_size = val64;
2186 params++;
2187
2188 /* hash start */
2189 val64 = strtoull(params, ¶ms, 10);
2190 if (*params != ' ')
2191 goto err;
2192 tgt->u.verity.hash_offset = val64;
2193 params++;
2194
2195 /* hash algorithm */
2196 str = strsep(¶ms, " ");
2197 if (!params)
2198 goto err;
2199 if (vp) {
2200 hash_name = strdup(str);
2201 if (!hash_name) {
2202 r = -ENOMEM;
2203 goto err;
2204 }
2205 }
2206
2207 /* root digest */
2208 str = strsep(¶ms, " ");
2209 if (!params)
2210 goto err;
2211 len = crypt_hex_to_bytes(str, &str2, 0);
2212 if (len < 0) {
2213 r = len;
2214 goto err;
2215 }
2216 tgt->u.verity.root_hash_size = len;
2217 if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH)
2218 root_hash = str2;
2219 else
2220 free(str2);
2221
2222 /* salt */
2223 str = strsep(¶ms, " ");
2224 if (vp) {
2225 if (!strcmp(str, "-")) {
2226 vp->salt_size = 0;
2227 vp->salt = NULL;
2228 } else {
2229 len = crypt_hex_to_bytes(str, &str2, 0);
2230 if (len < 0) {
2231 r = len;
2232 goto err;
2233 }
2234 vp->salt_size = len;
2235 salt = str2;
2236 }
2237 }
2238
2239 r = -EINVAL;
2240
2241 /* Features section, available since verity target version 1.3 */
2242 if (params) {
2243 /* Number of arguments */
2244 val64 = strtoull(params, ¶ms, 10);
2245 if (*params != ' ')
2246 goto err;
2247 params++;
2248
2249 features = (int)val64;
2250 for (i = 0; i < features; i++) {
2251 r = -EINVAL;
2252 if (!params)
2253 goto err;
2254 arg = strsep(¶ms, " ");
2255 if (!strcasecmp(arg, "ignore_corruption"))
2256 *act_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION;
2257 else if (!strcasecmp(arg, "restart_on_corruption"))
2258 *act_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
2259 else if (!strcasecmp(arg, "panic_on_corruption"))
2260 *act_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
2261 else if (!strcasecmp(arg, "ignore_zero_blocks"))
2262 *act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
2263 else if (!strcasecmp(arg, "check_at_most_once"))
2264 *act_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
2265 else if (!strcasecmp(arg, "use_fec_from_device")) {
2266 str = strsep(¶ms, " ");
2267 str2 = crypt_lookup_dev(str);
2268 if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
2269 r = device_alloc(cd, &fec_device, str2);
2270 if (r < 0 && r != -ENOTBLK) {
2271 free(str2);
2272 goto err;
2273 }
2274 }
2275 if (vp) {
2276 free(fec_dev_str);
2277 fec_dev_str = str2;
2278 } else
2279 free(str2);
2280 i++;
2281 } else if (!strcasecmp(arg, "fec_start")) {
2282 val64 = strtoull(params, ¶ms, 10);
2283 if (*params)
2284 params++;
2285 tgt->u.verity.fec_offset = val64;
2286 if (vp)
2287 vp->fec_area_offset = val64 * vp->hash_block_size;
2288 i++;
2289 } else if (!strcasecmp(arg, "fec_blocks")) {
2290 val64 = strtoull(params, ¶ms, 10);
2291 if (*params)
2292 params++;
2293 tgt->u.verity.fec_blocks = val64;
2294 i++;
2295 } else if (!strcasecmp(arg, "fec_roots")) {
2296 val32 = strtoul(params, ¶ms, 10);
2297 if (*params)
2298 params++;
2299 if (vp)
2300 vp->fec_roots = val32;
2301 i++;
2302 } else if (!strcasecmp(arg, "root_hash_sig_key_desc")) {
2303 str = strsep(¶ms, " ");
2304 if (!str)
2305 goto err;
2306 if (vp && !root_hash_sig_key_desc) {
2307 root_hash_sig_key_desc = strdup(str);
2308 if (!root_hash_sig_key_desc) {
2309 r = -ENOMEM;
2310 goto err;
2311 }
2312 /* not stored in params, but cannot be used without vp */
2313 vp->flags |= CRYPT_VERITY_ROOT_HASH_SIGNATURE;
2314 }
2315 i++;
2316 } else /* unknown option */
2317 goto err;
2318 }
2319
2320 /* All parameters should be processed */
2321 if (params && *params) {
2322 r = -EINVAL;
2323 goto err;
2324 }
2325 }
2326
2327 if (data_device)
2328 tgt->data_device = data_device;
2329 if (hash_device)
2330 tgt->u.verity.hash_device = hash_device;
2331 if (fec_device)
2332 tgt->u.verity.fec_device = fec_device;
2333 if (root_hash)
2334 tgt->u.verity.root_hash = root_hash;
2335 if (vp && hash_name)
2336 vp->hash_name = hash_name;
2337 if (vp && salt)
2338 vp->salt = salt;
2339 if (vp && fec_dev_str)
2340 vp->fec_device = fec_dev_str;
2341 if (root_hash_sig_key_desc)
2342 tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
2343
2344 return 0;
2345 err:
2346 device_free(cd, data_device);
2347 device_free(cd, hash_device);
2348 device_free(cd, fec_device);
2349 free(root_hash_sig_key_desc);
2350 free(root_hash);
2351 free(hash_name);
2352 free(salt);
2353 free(fec_dev_str);
2354 free(vp);
2355 return r;
2356 }
2357
2358 static int _dm_target_query_integrity(struct crypt_device *cd,
2359 uint32_t get_flags,
2360 char *params,
2361 struct dm_target *tgt,
2362 uint32_t *act_flags)
2363 {
2364 uint32_t val32;
2365 uint64_t val64;
2366 char c, *str, *str2, *arg;
2367 unsigned int i, features, val;
2368 ssize_t len;
2369 int r;
2370 struct device *data_device = NULL, *meta_device = NULL;
2371 char *integrity = NULL, *journal_crypt = NULL, *journal_integrity = NULL;
2372 struct volume_key *vk = NULL;
2373
2374 tgt->type = DM_INTEGRITY;
2375 tgt->direction = TARGET_QUERY;
2376
2377 /* data device */
2378 str = strsep(¶ms, " ");
2379 if (get_flags & DM_ACTIVE_DEVICE) {
2380 str2 = crypt_lookup_dev(str);
2381 r = device_alloc(cd, &data_device, str2);
2382 free(str2);
2383 if (r < 0 && r != -ENOTBLK)
2384 return r;
2385 }
2386
2387 r = -EINVAL;
2388
2389 /*offset */
2390 if (!params)
2391 goto err;
2392 val64 = strtoull(params, ¶ms, 10);
2393 if (!*params || *params != ' ')
2394 goto err;
2395 tgt->u.integrity.offset = val64;
2396
2397 /* tag size*/
2398 val32 = strtoul(params, ¶ms, 10);
2399 tgt->u.integrity.tag_size = val32;
2400 if (!*params || *params != ' ')
2401 goto err;
2402
2403 /* journal */
2404 c = toupper(*(++params));
2405 if (!*params || *(++params) != ' ' || (c != 'D' && c != 'J' && c != 'R' && c != 'B'))
2406 goto err;
2407 if (c == 'D')
2408 *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
2409 if (c == 'R')
2410 *act_flags |= CRYPT_ACTIVATE_RECOVERY;
2411 if (c == 'B') {
2412 *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
2413 *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;
2414 }
2415
2416 tgt->u.integrity.sector_size = SECTOR_SIZE;
2417
2418 /* Features section */
2419 if (params) {
2420 /* Number of arguments */
2421 val64 = strtoull(params, ¶ms, 10);
2422 if (*params != ' ')
2423 goto err;
2424 params++;
2425
2426 features = (int)val64;
2427 for (i = 0; i < features; i++) {
2428 r = -EINVAL;
2429 if (!params)
2430 goto err;
2431 arg = strsep(¶ms, " ");
2432 if (sscanf(arg, "journal_sectors:%u", &val) == 1)
2433 tgt->u.integrity.journal_size = val * SECTOR_SIZE;
2434 else if (sscanf(arg, "journal_watermark:%u", &val) == 1)
2435 tgt->u.integrity.journal_watermark = val;
2436 else if (sscanf(arg, "sectors_per_bit:%" PRIu64, &val64) == 1) {
2437 if (val64 > UINT_MAX)
2438 goto err;
2439 /* overloaded value for bitmap mode */
2440 tgt->u.integrity.journal_watermark = (unsigned int)val64;
2441 } else if (sscanf(arg, "commit_time:%u", &val) == 1)
2442 tgt->u.integrity.journal_commit_time = val;
2443 else if (sscanf(arg, "bitmap_flush_interval:%u", &val) == 1)
2444 /* overloaded value for bitmap mode */
2445 tgt->u.integrity.journal_commit_time = val;
2446 else if (sscanf(arg, "interleave_sectors:%u", &val) == 1)
2447 tgt->u.integrity.interleave_sectors = val;
2448 else if (sscanf(arg, "block_size:%u", &val) == 1)
2449 tgt->u.integrity.sector_size = val;
2450 else if (sscanf(arg, "buffer_sectors:%u", &val) == 1)
2451 tgt->u.integrity.buffer_sectors = val;
2452 else if (!strncmp(arg, "internal_hash:", 14) && !integrity) {
2453 str = &arg[14];
2454 arg = strsep(&str, ":");
2455 if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
2456 integrity = strdup(arg);
2457 if (!integrity) {
2458 r = -ENOMEM;
2459 goto err;
2460 }
2461 }
2462
2463 if (str) {
2464 len = crypt_hex_to_bytes(str, &str2, 1);
2465 if (len < 0) {
2466 r = len;
2467 goto err;
2468 }
2469
2470 r = 0;
2471 if (get_flags & DM_ACTIVE_CRYPT_KEY) {
2472 vk = crypt_alloc_volume_key(len, str2);
2473 if (!vk)
2474 r = -ENOMEM;
2475 } else if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
2476 vk = crypt_alloc_volume_key(len, NULL);
2477 if (!vk)
2478 r = -ENOMEM;
2479 }
2480 crypt_safe_free(str2);
2481 if (r < 0)
2482 goto err;
2483 }
2484 } else if (!strncmp(arg, "meta_device:", 12) && !meta_device) {
2485 if (get_flags & DM_ACTIVE_DEVICE) {
2486 str = crypt_lookup_dev(&arg[12]);
2487 r = device_alloc(cd, &meta_device, str);
2488 free(str);
2489 if (r < 0 && r != -ENOTBLK)
2490 goto err;
2491 }
2492 } else if (!strncmp(arg, "journal_crypt:", 14) && !journal_crypt) {
2493 str = &arg[14];
2494 arg = strsep(&str, ":");
2495 if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
2496 journal_crypt = strdup(arg);
2497 if (!journal_crypt) {
2498 r = -ENOMEM;
2499 goto err;
2500 }
2501 }
2502 } else if (!strncmp(arg, "journal_mac:", 12) && !journal_integrity) {
2503 str = &arg[12];
2504 arg = strsep(&str, ":");
2505 if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
2506 journal_integrity = strdup(arg);
2507 if (!journal_integrity) {
2508 r = -ENOMEM;
2509 goto err;
2510 }
2511 }
2512 } else if (!strcmp(arg, "recalculate")) {
2513 *act_flags |= CRYPT_ACTIVATE_RECALCULATE;
2514 } else if (!strcmp(arg, "reset_recalculate")) {
2515 *act_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET;
2516 } else if (!strcmp(arg, "fix_padding")) {
2517 tgt->u.integrity.fix_padding = true;
2518 } else if (!strcmp(arg, "fix_hmac")) {
2519 tgt->u.integrity.fix_hmac = true;
2520 } else if (!strcmp(arg, "legacy_recalculate")) {
2521 tgt->u.integrity.legacy_recalc = true;
2522 } else if (!strcmp(arg, "allow_discards")) {
2523 *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
2524 } else /* unknown option */
2525 goto err;
2526 }
2527
2528 /* All parameters should be processed */
2529 if (params && *params) {
2530 r = -EINVAL;
2531 goto err;
2532 }
2533 }
2534
2535 if (data_device)
2536 tgt->data_device = data_device;
2537 if (meta_device)
2538 tgt->u.integrity.meta_device = meta_device;
2539 if (integrity)
2540 tgt->u.integrity.integrity = integrity;
2541 if (journal_crypt)
2542 tgt->u.integrity.journal_crypt = journal_crypt;
2543 if (journal_integrity)
2544 tgt->u.integrity.journal_integrity = journal_integrity;
2545 if (vk)
2546 tgt->u.integrity.vk = vk;
2547 return 0;
2548 err:
2549 device_free(cd, data_device);
2550 device_free(cd, meta_device);
2551 free(integrity);
2552 free(journal_crypt);
2553 free(journal_integrity);
2554 crypt_free_volume_key(vk);
2555 return r;
2556 }
2557
2558 static int _dm_target_query_linear(struct crypt_device *cd, struct dm_target *tgt,
2559 uint32_t get_flags, char *params)
2560 {
2561 uint64_t val64;
2562 char *rdevice, *arg;
2563 int r;
2564 struct device *device = NULL;
2565
2566 /* device */
2567 rdevice = strsep(¶ms, " ");
2568 if (get_flags & DM_ACTIVE_DEVICE) {
2569 arg = crypt_lookup_dev(rdevice);
2570 r = device_alloc(cd, &device, arg);
2571 free(arg);
2572 if (r < 0 && r != -ENOTBLK)
2573 return r;
2574 }
2575
2576 r = -EINVAL;
2577
2578 /*offset */
2579 if (!params)
2580 goto err;
2581 val64 = strtoull(params, ¶ms, 10);
2582
2583 /* params should be empty now */
2584 if (*params)
2585 goto err;
2586
2587 tgt->type = DM_LINEAR;
2588 tgt->direction = TARGET_QUERY;
2589 tgt->data_device = device;
2590 tgt->u.linear.offset = val64;
2591
2592 return 0;
2593 err:
2594 device_free(cd, device);
2595 return r;
2596 }
2597
2598 static int _dm_target_query_error(struct crypt_device *cd __attribute__((unused)), struct dm_target *tgt)
2599 {
2600 tgt->type = DM_ERROR;
2601 tgt->direction = TARGET_QUERY;
2602
2603 return 0;
2604 }
2605
2606 static int _dm_target_query_zero(struct crypt_device *cd __attribute__((unused)), struct dm_target *tgt)
2607 {
2608 tgt->type = DM_ZERO;
2609 tgt->direction = TARGET_QUERY;
2610
2611 return 0;
2612 }
2613
2614 /*
2615 * on error retval has to be negative
2616 *
2617 * also currently any _dm_target_query fn does not perform cleanup on error
2618 */
2619 static int dm_target_query(struct crypt_device *cd, struct dm_target *tgt, const uint64_t *start,
2620 const uint64_t *length, const char *target_type,
2621 char *params, uint32_t get_flags, uint32_t *act_flags)
2622 {
2623 int r = -ENOTSUP;
2624
2625 if (!strcmp(target_type, DM_CRYPT_TARGET))
2626 r = _dm_target_query_crypt(cd, get_flags, params, tgt, act_flags);
2627 else if (!strcmp(target_type, DM_VERITY_TARGET))
2628 r = _dm_target_query_verity(cd, get_flags, params, tgt, act_flags);
2629 else if (!strcmp(target_type, DM_INTEGRITY_TARGET))
2630 r = _dm_target_query_integrity(cd, get_flags, params, tgt, act_flags);
2631 else if (!strcmp(target_type, DM_LINEAR_TARGET))
2632 r = _dm_target_query_linear(cd, tgt, get_flags, params);
2633 else if (!strcmp(target_type, DM_ERROR_TARGET))
2634 r = _dm_target_query_error(cd, tgt);
2635 else if (!strcmp(target_type, DM_ZERO_TARGET))
2636 r = _dm_target_query_zero(cd, tgt);
2637
2638 if (!r) {
2639 tgt->offset = *start;
2640 tgt->size = *length;
2641 }
2642
2643 return r;
2644 }
2645
2646 static int _dm_query_device(struct crypt_device *cd, const char *name,
2647 uint32_t get_flags, struct crypt_dm_active_device *dmd)
2648 {
2649 struct dm_target *t;
2650 struct dm_task *dmt;
2651 struct dm_info dmi;
2652 uint64_t start, length;
2653 char *target_type, *params;
2654 const char *tmp_uuid;
2655 void *next = NULL;
2656 int r = -EINVAL;
2657
2658 t = &dmd->segment;
2659
2660 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
2661 return r;
2662 if (!dm_task_secure_data(dmt))
2663 goto out;
2664 if (!dm_task_set_name(dmt, name))
2665 goto out;
2666 r = -ENODEV;
2667 if (!dm_task_run(dmt))
2668 goto out;
2669
2670 r = -EINVAL;
2671 if (!dm_task_get_info(dmt, &dmi))
2672 goto out;
2673
2674 if (!dmi.exists) {
2675 r = -ENODEV;
2676 goto out;
2677 }
2678
2679 if (dmi.target_count <= 0) {
2680 r = -EINVAL;
2681 goto out;
2682 }
2683
2684 /* Never allow to return empty key */
2685 if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi.suspended) {
2686 log_dbg(cd, "Cannot read volume key while suspended.");
2687 r = -EINVAL;
2688 goto out;
2689 }
2690
2691 r = dm_targets_allocate(&dmd->segment, dmi.target_count);
2692 if (r)
2693 goto out;
2694
2695 do {
2696 next = dm_get_next_target(dmt, next, &start, &length,
2697 &target_type, ¶ms);
2698
2699 r = dm_target_query(cd, t, &start, &length, target_type, params, get_flags, &dmd->flags);
2700 if (!r && t->type == DM_VERITY) {
2701 r = _dm_status_verity_ok(cd, name);
2702 if (r == 0)
2703 dmd->flags |= CRYPT_ACTIVATE_CORRUPTED;
2704 }
2705
2706 if (r < 0) {
2707 if (r != -ENOTSUP)
2708 log_err(cd, _("Failed to query dm-%s segment."), target_type);
2709 goto out;
2710 }
2711
2712 dmd->size += length;
2713 t = t->next;
2714 } while (next && t);
2715
2716 if (dmi.read_only)
2717 dmd->flags |= CRYPT_ACTIVATE_READONLY;
2718
2719 if (dmi.suspended)
2720 dmd->flags |= CRYPT_ACTIVATE_SUSPENDED;
2721
2722 tmp_uuid = dm_task_get_uuid(dmt);
2723 if (!tmp_uuid)
2724 dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
2725 else if (get_flags & DM_ACTIVE_UUID) {
2726 if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
2727 dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
2728 }
2729
2730 dmd->holders = 0;
2731 #if (HAVE_DECL_DM_DEVICE_HAS_HOLDERS && HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS)
2732 if (get_flags & DM_ACTIVE_HOLDERS)
2733 dmd->holders = (dm_device_has_mounted_fs(dmi.major, dmi.minor) ||
2734 dm_device_has_holders(dmi.major, dmi.minor));
2735 #endif
2736
2737 r = (dmi.open_count > 0);
2738 out:
2739 dm_task_destroy(dmt);
2740
2741 if (r < 0)
2742 dm_targets_free(cd, dmd);
2743
2744 return r;
2745 }
2746
2747 int dm_query_device(struct crypt_device *cd, const char *name,
2748 uint32_t get_flags, struct crypt_dm_active_device *dmd)
2749 {
2750 int r;
2751
2752 if (!dmd)
2753 return -EINVAL;
2754
2755 memset(dmd, 0, sizeof(*dmd));
2756
2757 if (dm_init_context(cd, DM_UNKNOWN))
2758 return -ENOTSUP;
2759
2760 r = _dm_query_device(cd, name, get_flags, dmd);
2761
2762 dm_exit_context();
2763 return r;
2764 }
2765
2766 static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps, char **names, size_t names_offset, size_t names_length)
2767 {
2768 #if HAVE_DECL_DM_DEVICE_GET_NAME
2769 struct crypt_dm_active_device dmd;
2770 char dmname[PATH_MAX];
2771 unsigned i;
2772 int r, major, minor, count = 0;
2773
2774 if (!prefix || !deps)
2775 return -EINVAL;
2776
2777 for (i = 0; i < deps->count; i++) {
2778 major = major(deps->device[i]);
2779 if (!dm_is_dm_major(major))
2780 continue;
2781
2782 minor = minor(deps->device[i]);
2783 if (!dm_device_get_name(major, minor, 0, dmname, PATH_MAX))
2784 return -EINVAL;
2785
2786 memset(&dmd, 0, sizeof(dmd));
2787 r = _dm_query_device(cd, dmname, DM_ACTIVE_UUID, &dmd);
2788 if (r < 0)
2789 continue;
2790
2791 if (!dmd.uuid ||
2792 strncmp(prefix, dmd.uuid, strlen(prefix)) ||
2793 crypt_string_in(dmname, names, names_length))
2794 *dmname = '\0';
2795
2796 dm_targets_free(cd, &dmd);
2797 free(CONST_CAST(void*)dmd.uuid);
2798
2799 if ((size_t)count >= (names_length - names_offset))
2800 return -ENOMEM;
2801
2802 if (*dmname && !(names[names_offset + count++] = strdup(dmname)))
2803 return -ENOMEM;
2804 }
2805
2806 return count;
2807 #else
2808 return -EINVAL;
2809 #endif
2810 }
2811
2812 int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix, char **names, size_t names_length)
2813 {
2814 struct dm_task *dmt;
2815 struct dm_info dmi;
2816 struct dm_deps *deps;
2817 int r = -EINVAL;
2818 size_t i, last = 0, offset = 0;
2819
2820 if (!name || !names_length || !names)
2821 return -EINVAL;
2822
2823 if (dm_init_context(cd, DM_UNKNOWN))
2824 return -ENOTSUP;
2825
2826 while (name) {
2827 if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
2828 goto out;
2829 if (!dm_task_set_name(dmt, name))
2830 goto out;
2831
2832 r = -ENODEV;
2833 if (!dm_task_run(dmt))
2834 goto out;
2835
2836 r = -EINVAL;
2837 if (!dm_task_get_info(dmt, &dmi))
2838 goto out;
2839 if (!(deps = dm_task_get_deps(dmt)))
2840 goto out;
2841
2842 r = -ENODEV;
2843 if (!dmi.exists)
2844 goto out;
2845
2846 r = _process_deps(cd, prefix, deps, names, offset, names_length - 1);
2847 if (r < 0)
2848 goto out;
2849
2850 dm_task_destroy(dmt);
2851 dmt = NULL;
2852
2853 offset += r;
2854 name = names[last++];
2855 }
2856
2857 r = 0;
2858 out:
2859 if (r < 0) {
2860 for (i = 0; i < names_length - 1; i++)
2861 free(names[i]);
2862 *names = NULL;
2863 }
2864
2865 if (dmt)
2866 dm_task_destroy(dmt);
2867
2868 dm_exit_context();
2869 return r;
2870 }
2871
2872 static int _dm_message(const char *name, const char *msg)
2873 {
2874 int r = 0;
2875 struct dm_task *dmt;
2876
2877 if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
2878 return 0;
2879
2880 if (!dm_task_secure_data(dmt))
2881 goto out;
2882
2883 if (name && !dm_task_set_name(dmt, name))
2884 goto out;
2885
2886 if (!dm_task_set_sector(dmt, (uint64_t) 0))
2887 goto out;
2888
2889 if (!dm_task_set_message(dmt, msg))
2890 goto out;
2891
2892 r = dm_task_run(dmt);
2893 out:
2894 dm_task_destroy(dmt);
2895 return r;
2896 }
2897
2898 int dm_suspend_device(struct crypt_device *cd, const char *name, uint32_t dmflags)
2899 {
2900 uint32_t dmt_flags;
2901 int r = -ENOTSUP;
2902
2903 if (dm_init_context(cd, DM_UNKNOWN))
2904 return r;
2905
2906 if (dmflags & DM_SUSPEND_WIPE_KEY) {
2907 if (dm_flags(cd, DM_CRYPT, &dmt_flags))
2908 goto out;
2909
2910 if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
2911 goto out;
2912 }
2913
2914 r = -EINVAL;
2915
2916 if (!_dm_simple(DM_DEVICE_SUSPEND, name, dmflags))
2917 goto out;
2918
2919 if (dmflags & DM_SUSPEND_WIPE_KEY) {
2920 if (!_dm_message(name, "key wipe")) {
2921 _dm_resume_device(name, 0);
2922 goto out;
2923 }
2924 }
2925
2926 r = 0;
2927 out:
2928 dm_exit_context();
2929 return r;
2930 }
2931
2932 int dm_resume_device(struct crypt_device *cd, const char *name, uint32_t dmflags)
2933 {
2934 int r;
2935
2936 if (dm_init_context(cd, DM_UNKNOWN))
2937 return -ENOTSUP;
2938
2939 r = _dm_resume_device(name, dmflags);
2940
2941 dm_exit_context();
2942
2943 return r;
2944 }
2945
2946 int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
2947 const struct volume_key *vk)
2948 {
2949 uint32_t dmt_flags;
2950 int msg_size;
2951 char *msg = NULL;
2952 int r = -ENOTSUP;
2953
2954 if (dm_init_context(cd, DM_CRYPT) || dm_flags(cd, DM_CRYPT, &dmt_flags))
2955 return -ENOTSUP;
2956
2957 if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
2958 goto out;
2959
2960 if (!vk->keylength)
2961 msg_size = 11; // key set -
2962 else if (vk->key_description)
2963 msg_size = strlen(vk->key_description) + int_log10(vk->keylength) + 18;
2964 else
2965 msg_size = vk->keylength * 2 + 10; // key set <key>
2966
2967 msg = crypt_safe_alloc(msg_size);
2968 if (!msg) {
2969 r = -ENOMEM;
2970 goto out;
2971 }
2972
2973 strcpy(msg, "key set ");
2974 if (!vk->keylength)
2975 snprintf(msg + 8, msg_size - 8, "-");
2976 else if (vk->key_description)
2977 snprintf(msg + 8, msg_size - 8, ":%zu:logon:%s", vk->keylength, vk->key_description);
2978 else
2979 hex_key(&msg[8], vk->keylength, vk->key);
2980
2981 if (!_dm_message(name, msg) ||
2982 _dm_resume_device(name, 0)) {
2983 r = -EINVAL;
2984 goto out;
2985 }
2986 r = 0;
2987 out:
2988 crypt_safe_free(msg);
2989 dm_exit_context();
2990 return r;
2991 }
2992
2993 int dm_cancel_deferred_removal(const char *name)
2994 {
2995 return _dm_message(name, "@cancel_deferred_remove") ? 0 : -ENOTSUP;
2996 }
2997
2998 const char *dm_get_dir(void)
2999 {
3000 return dm_dir();
3001 }
3002
3003 int dm_is_dm_device(int major)
3004 {
3005 return dm_is_dm_major((uint32_t)major);
3006 }
3007
3008 int dm_is_dm_kernel_name(const char *name)
3009 {
3010 return strncmp(name, "dm-", 3) ? 0 : 1;
3011 }
3012
3013 int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3014 struct device *data_device, struct volume_key *vk, const char *cipher,
3015 uint64_t iv_offset, uint64_t data_offset, const char *integrity, uint32_t tag_size,
3016 uint32_t sector_size)
3017 {
3018 char *dm_integrity = NULL;
3019
3020 if (tag_size) {
3021 /* Space for IV metadata only */
3022 dm_integrity = strdup(integrity ?: "none");
3023 if (!dm_integrity)
3024 return -ENOMEM;
3025 }
3026
3027 tgt->data_device = data_device;
3028
3029 tgt->type = DM_CRYPT;
3030 tgt->direction = TARGET_SET;
3031 tgt->u.crypt.vk = vk;
3032 tgt->offset = seg_offset;
3033 tgt->size = seg_size;
3034
3035 tgt->u.crypt.cipher = cipher;
3036 tgt->u.crypt.integrity = dm_integrity;
3037 tgt->u.crypt.iv_offset = iv_offset;
3038 tgt->u.crypt.offset = data_offset;
3039 tgt->u.crypt.tag_size = tag_size;
3040 tgt->u.crypt.sector_size = sector_size;
3041
3042 return 0;
3043 }
3044
3045 int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3046 struct device *data_device, struct device *hash_device, struct device *fec_device,
3047 const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
3048 uint64_t hash_offset_block, uint64_t fec_blocks, struct crypt_params_verity *vp)
3049 {
3050 if (!data_device || !hash_device || !vp)
3051 return -EINVAL;
3052
3053 tgt->type = DM_VERITY;
3054 tgt->direction = TARGET_SET;
3055 tgt->offset = seg_offset;
3056 tgt->size = seg_size;
3057 tgt->data_device = data_device;
3058
3059 tgt->u.verity.hash_device = hash_device;
3060 tgt->u.verity.fec_device = fec_device;
3061 tgt->u.verity.root_hash = root_hash;
3062 tgt->u.verity.root_hash_size = root_hash_size;
3063 tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
3064 tgt->u.verity.hash_offset = hash_offset_block;
3065 tgt->u.verity.fec_offset = vp->fec_area_offset / vp->hash_block_size;
3066 tgt->u.verity.fec_blocks = fec_blocks;
3067 tgt->u.verity.vp = vp;
3068
3069 return 0;
3070 }
3071
3072 int dm_integrity_target_set(struct crypt_device *cd,
3073 struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3074 struct device *meta_device,
3075 struct device *data_device, uint64_t tag_size, uint64_t offset,
3076 uint32_t sector_size, struct volume_key *vk,
3077 struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key,
3078 const struct crypt_params_integrity *ip)
3079 {
3080 uint32_t dmi_flags;
3081
3082 if (!data_device)
3083 return -EINVAL;
3084
3085 _dm_check_versions(cd, DM_INTEGRITY);
3086
3087 tgt->type = DM_INTEGRITY;
3088 tgt->direction = TARGET_SET;
3089 tgt->offset = seg_offset;
3090 tgt->size = seg_size;
3091 tgt->data_device = data_device;
3092 if (meta_device != data_device)
3093 tgt->u.integrity.meta_device = meta_device;
3094 tgt->u.integrity.tag_size = tag_size;
3095 tgt->u.integrity.offset = offset;
3096 tgt->u.integrity.sector_size = sector_size;
3097
3098 tgt->u.integrity.vk = vk;
3099 tgt->u.integrity.journal_crypt_key = journal_crypt_key;
3100 tgt->u.integrity.journal_integrity_key = journal_mac_key;
3101
3102 if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
3103 (dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED) &&
3104 !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING))
3105 tgt->u.integrity.fix_padding = true;
3106
3107 if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
3108 (dmi_flags & DM_INTEGRITY_FIX_HMAC_SUPPORTED) &&
3109 !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC))
3110 tgt->u.integrity.fix_hmac = true;
3111
3112 /* This flag can be backported, just try to set it always */
3113 if (crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC)
3114 tgt->u.integrity.legacy_recalc = true;
3115
3116 if (ip) {
3117 tgt->u.integrity.journal_size = ip->journal_size;
3118 tgt->u.integrity.journal_watermark = ip->journal_watermark;
3119 tgt->u.integrity.journal_commit_time = ip->journal_commit_time;
3120 tgt->u.integrity.interleave_sectors = ip->interleave_sectors;
3121 tgt->u.integrity.buffer_sectors = ip->buffer_sectors;
3122 tgt->u.integrity.journal_integrity = ip->journal_integrity;
3123 tgt->u.integrity.journal_crypt = ip->journal_crypt;
3124 tgt->u.integrity.integrity = ip->integrity;
3125 }
3126
3127 return 0;
3128 }
3129
3130 int dm_linear_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3131 struct device *data_device, uint64_t data_offset)
3132 {
3133 if (!data_device)
3134 return -EINVAL;
3135
3136 tgt->type = DM_LINEAR;
3137 tgt->direction = TARGET_SET;
3138 tgt->offset = seg_offset;
3139 tgt->size = seg_size;
3140 tgt->data_device = data_device;
3141
3142 tgt->u.linear.offset = data_offset;
3143
3144 return 0;
3145 }
3146
3147 int dm_zero_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size)
3148 {
3149 tgt->type = DM_ZERO;
3150 tgt->direction = TARGET_SET;
3151 tgt->offset = seg_offset;
3152 tgt->size = seg_size;
3153
3154 return 0;
3155 }