]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/encrypt.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / io / encrypt.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
0cf66b0f 2/*
c304c84f 3 * Copyright 2016, 2019 Google LLC
0cf66b0f 4 * Author: Eric Biggers <ebiggers@google.com>
0cf66b0f
EB
5 */
6
dfe209d8
EB
7#ifdef OVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG
8# define fscrypt_add_key_arg sys_fscrypt_add_key_arg
9#endif
e97caf71
EB
10#ifdef OVERRIDE_SYSTEM_FSCRYPT_POLICY_V2
11# define fscrypt_policy_v2 sys_fscrypt_policy_v2
12# define fscrypt_get_policy_ex_arg sys_fscrypt_get_policy_ex_arg
13#endif
0cf66b0f
EB
14#include "platform_defs.h"
15#include "command.h"
16#include "init.h"
42b4c8e8 17#include "libfrog/paths.h"
0cf66b0f
EB
18#include "io.h"
19
20#ifndef ARRAY_SIZE
21#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
22#endif
23
24/*
336e7c19
EB
25 * Declare the fscrypt ioctls if needed, since someone may be compiling xfsprogs
26 * with old kernel headers. But <linux/fs.h> has already been included, so be
27 * careful not to declare things twice.
0cf66b0f
EB
28 */
29
336e7c19 30/* first batch of ioctls (Linux headers v4.6+) */
0cf66b0f 31#ifndef FS_IOC_SET_ENCRYPTION_POLICY
336e7c19
EB
32#define fscrypt_policy fscrypt_policy_v1
33#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy)
34#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
35#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy)
36#endif
37
e97caf71
EB
38/*
39 * Since the log2_data_unit_size field was added later than fscrypt_policy_v2
40 * itself, we may need to override the system definition to get that field.
41 * And also fscrypt_get_policy_ex_arg since it contains fscrypt_policy_v2.
42 */
43#if !defined(FS_IOC_GET_ENCRYPTION_POLICY_EX) || \
44 defined(OVERRIDE_SYSTEM_FSCRYPT_POLICY_V2)
45#undef fscrypt_policy_v2
46struct fscrypt_policy_v2 {
47 __u8 version;
48 __u8 contents_encryption_mode;
49 __u8 filenames_encryption_mode;
50 __u8 flags;
51 __u8 log2_data_unit_size;
52 __u8 __reserved[3];
53 __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
54};
55
56#undef fscrypt_get_policy_ex_arg
57struct fscrypt_get_policy_ex_arg {
58 __u64 policy_size; /* input/output */
59 union {
60 __u8 version;
61 struct fscrypt_policy_v1 v1;
62 struct fscrypt_policy_v2 v2;
63 } policy; /* output */
64};
65#endif
66
336e7c19
EB
67/*
68 * Second batch of ioctls (Linux headers v5.4+), plus some renamings from FS_ to
69 * FSCRYPT_. We don't bother defining the old names here.
70 */
71#ifndef FS_IOC_GET_ENCRYPTION_POLICY_EX
72
73#define FSCRYPT_POLICY_FLAGS_PAD_4 0x00
74#define FSCRYPT_POLICY_FLAGS_PAD_8 0x01
75#define FSCRYPT_POLICY_FLAGS_PAD_16 0x02
76#define FSCRYPT_POLICY_FLAGS_PAD_32 0x03
77#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03
78#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04
79
80#define FSCRYPT_MODE_AES_256_XTS 1
81#define FSCRYPT_MODE_AES_256_CTS 4
82#define FSCRYPT_MODE_AES_128_CBC 5
83#define FSCRYPT_MODE_AES_128_CTS 6
84#define FSCRYPT_MODE_ADIANTUM 9
85
86/*
87 * In the headers for Linux v4.6 through v5.3, 'struct fscrypt_policy_v1' is
88 * already defined under its old name, 'struct fscrypt_policy'. But it's fine
89 * to define it under its new name too.
90 *
91 * Note: "v1" policies really are version "0" in the API.
92 */
93#define FSCRYPT_POLICY_V1 0
94#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8
95struct fscrypt_policy_v1 {
96 __u8 version;
97 __u8 contents_encryption_mode;
98 __u8 filenames_encryption_mode;
99 __u8 flags;
100 __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
101};
0cf66b0f 102
336e7c19
EB
103#define FSCRYPT_POLICY_V2 2
104#define FSCRYPT_KEY_IDENTIFIER_SIZE 16
e97caf71 105/* struct fscrypt_policy_v2 was defined earlier */
336e7c19
EB
106
107#define FSCRYPT_MAX_KEY_SIZE 64
108
109#define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */
e97caf71 110/* struct fscrypt_get_policy_ex_arg was defined earlier */
336e7c19
EB
111
112#define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1
113#define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER 2
114struct fscrypt_key_specifier {
115 __u32 type; /* one of FSCRYPT_KEY_SPEC_TYPE_* */
116 __u32 __reserved;
117 union {
118 __u8 __reserved[32]; /* reserve some extra space */
119 __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
120 __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
121 } u;
122};
123
dfe209d8 124/* FS_IOC_ADD_ENCRYPTION_KEY is defined later */
336e7c19
EB
125
126#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
127#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
128struct fscrypt_remove_key_arg {
129 struct fscrypt_key_specifier key_spec;
130#define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY 0x00000001
131#define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS 0x00000002
132 __u32 removal_status_flags; /* output */
133 __u32 __reserved[5];
134};
135
136#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg)
137struct fscrypt_get_key_status_arg {
138 /* input */
139 struct fscrypt_key_specifier key_spec;
140 __u32 __reserved[6];
141
142 /* output */
143#define FSCRYPT_KEY_STATUS_ABSENT 1
144#define FSCRYPT_KEY_STATUS_PRESENT 2
145#define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3
146 __u32 status;
147#define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF 0x00000001
148 __u32 status_flags;
149 __u32 user_count;
150 __u32 __out_reserved[13];
151};
152
153#endif /* !FS_IOC_GET_ENCRYPTION_POLICY_EX */
0cf66b0f 154
dfe209d8
EB
155/*
156 * Since the key_id field was added later than struct fscrypt_add_key_arg
157 * itself, we may need to override the system definition to get that field.
158 */
159#if !defined(FS_IOC_ADD_ENCRYPTION_KEY) || \
160 defined(OVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG)
161#undef fscrypt_add_key_arg
162struct fscrypt_add_key_arg {
163 struct fscrypt_key_specifier key_spec;
164 __u32 raw_size;
165 __u32 key_id;
166 __u32 __reserved[8];
167 __u8 raw[];
168};
169#endif
170
171#ifndef FS_IOC_ADD_ENCRYPTION_KEY
172# define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg)
173#endif
174
eb6c66e6
EB
175static const struct {
176 __u8 mode;
177 const char *name;
178} available_modes[] = {
179 {FSCRYPT_MODE_AES_256_XTS, "AES-256-XTS"},
180 {FSCRYPT_MODE_AES_256_CTS, "AES-256-CTS"},
7cde2c28
EB
181 {FSCRYPT_MODE_AES_128_CBC, "AES-128-CBC"},
182 {FSCRYPT_MODE_AES_128_CTS, "AES-128-CTS"},
183 {FSCRYPT_MODE_ADIANTUM, "Adiantum"},
eb6c66e6
EB
184};
185
0cf66b0f
EB
186static cmdinfo_t get_encpolicy_cmd;
187static cmdinfo_t set_encpolicy_cmd;
ba71de04 188static cmdinfo_t add_enckey_cmd;
c808a097 189static cmdinfo_t rm_enckey_cmd;
dafb55f9 190static cmdinfo_t enckey_status_cmd;
0cf66b0f 191
c304c84f
EB
192static void
193get_encpolicy_help(void)
194{
195 printf(_(
196"\n"
197" display the encryption policy of the current file\n"
198"\n"
199" -1 -- Use only the old ioctl to get the encryption policy.\n"
200" This only works if the file has a v1 encryption policy.\n"
201" -t -- Test whether v2 encryption policies are supported.\n"
202" Prints \"supported\", \"unsupported\", or an error message.\n"
203"\n"));
204}
205
0cf66b0f
EB
206static void
207set_encpolicy_help(void)
208{
eb6c66e6
EB
209 int i;
210
0cf66b0f
EB
211 printf(_(
212"\n"
213" assign an encryption policy to the currently open file\n"
214"\n"
215" Examples:\n"
a7a5e44c
EB
216" 'set_encpolicy' - assign v1 policy with default key descriptor\n"
217" (0000000000000000)\n"
218" 'set_encpolicy -v 2' - assign v2 policy with default key identifier\n"
219" (00000000000000000000000000000000)\n"
220" 'set_encpolicy 0000111122223333' - assign v1 policy with given key descriptor\n"
221" 'set_encpolicy 00001111222233334444555566667777' - assign v2 policy with given\n"
222" key identifier\n"
0cf66b0f
EB
223"\n"
224" -c MODE -- contents encryption mode\n"
225" -n MODE -- filenames encryption mode\n"
226" -f FLAGS -- policy flags\n"
e97caf71 227" -s LOG2_DUSIZE -- log2 of data unit size\n"
a7a5e44c 228" -v VERSION -- policy version\n"
0cf66b0f 229"\n"
eb6c66e6
EB
230" MODE can be numeric or one of the following predefined values:\n"));
231 printf(" ");
232 for (i = 0; i < ARRAY_SIZE(available_modes); i++) {
233 printf("%s", available_modes[i].name);
234 if (i != ARRAY_SIZE(available_modes) - 1)
235 printf(", ");
236 }
237 printf("\n");
238 printf(_(
0cf66b0f
EB
239" FLAGS and VERSION must be numeric.\n"
240"\n"
241" Note that it's only possible to set an encryption policy on an empty\n"
242" directory. It's then inherited by new files and subdirectories.\n"
243"\n"));
244}
245
ba71de04
EB
246static void
247add_enckey_help(void)
248{
249 printf(_(
250"\n"
251" add an encryption key to the filesystem\n"
252"\n"
253" Examples:\n"
254" 'add_enckey' - add key for v2 policies\n"
255" 'add_enckey -d 0000111122223333' - add key for v1 policies w/ given descriptor\n"
256"\n"
dfe209d8 257"Unless -k is given, the key in binary is read from standard input.\n"
ba71de04 258" -d DESCRIPTOR -- master_key_descriptor\n"
dfe209d8 259" -k KEY_ID -- ID of fscrypt-provisioning key containing the raw key\n"
ba71de04
EB
260"\n"));
261}
262
c808a097
EB
263static void
264rm_enckey_help(void)
265{
266 printf(_(
267"\n"
268" remove an encryption key from the filesystem\n"
269"\n"
270" Examples:\n"
271" 'rm_enckey 0000111122223333' - remove key for v1 policies w/ given descriptor\n"
272" 'rm_enckey 00001111222233334444555566667777' - remove key for v2 policies w/ given identifier\n"
273"\n"
274" -a -- remove key for all users who have added it (privileged operation)\n"
275"\n"));
276}
277
dafb55f9
EB
278static void
279enckey_status_help(void)
280{
281 printf(_(
282"\n"
283" get the status of a filesystem encryption key\n"
284"\n"
285" Examples:\n"
286" 'enckey_status 0000111122223333' - get status of v1 policy key\n"
287" 'enckey_status 00001111222233334444555566667777' - get status of v2 policy key\n"
288"\n"));
289}
290
0cf66b0f
EB
291static bool
292parse_byte_value(const char *arg, __u8 *value_ret)
293{
294 long value;
295 char *tmp;
296
297 value = strtol(arg, &tmp, 0);
298 if (value < 0 || value > 255 || tmp == arg || *tmp != '\0')
299 return false;
300 *value_ret = value;
301 return true;
302}
303
304static bool
305parse_mode(const char *arg, __u8 *mode_ret)
306{
307 int i;
308
309 for (i = 0; i < ARRAY_SIZE(available_modes); i++) {
310 if (strcmp(arg, available_modes[i].name) == 0) {
311 *mode_ret = available_modes[i].mode;
312 return true;
313 }
314 }
315
316 return parse_byte_value(arg, mode_ret);
317}
318
319static const char *
320mode2str(__u8 mode)
321{
322 static char buf[32];
323 int i;
324
325 for (i = 0; i < ARRAY_SIZE(available_modes); i++)
326 if (mode == available_modes[i].mode)
327 return available_modes[i].name;
328
329 sprintf(buf, "0x%02x", mode);
330 return buf;
331}
332
a7a5e44c
EB
333static int
334hexchar2bin(char c)
335{
336 if (c >= '0' && c <= '9')
337 return c - '0';
338 if (c >= 'a' && c <= 'f')
339 return 10 + (c - 'a');
340 if (c >= 'A' && c <= 'F')
341 return 10 + (c - 'A');
342 return -1;
343}
344
345static bool
346hex2bin(const char *hex, __u8 *bin, size_t bin_len)
347{
348 if (strlen(hex) != 2 * bin_len)
349 return false;
350
351 while (bin_len--) {
352 int hi = hexchar2bin(*hex++);
353 int lo = hexchar2bin(*hex++);
354
355 if (hi < 0 || lo < 0)
356 return false;
357 *bin++ = (hi << 4) | lo;
358 }
359 return true;
360}
361
0cf66b0f 362static const char *
c304c84f 363keydesc2str(const __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE])
0cf66b0f 364{
336e7c19 365 static char buf[2 * FSCRYPT_KEY_DESCRIPTOR_SIZE + 1];
0cf66b0f
EB
366 int i;
367
336e7c19 368 for (i = 0; i < FSCRYPT_KEY_DESCRIPTOR_SIZE; i++)
0cf66b0f
EB
369 sprintf(&buf[2 * i], "%02x", master_key_descriptor[i]);
370
371 return buf;
372}
373
c304c84f
EB
374static const char *
375keyid2str(const __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
376{
377 static char buf[2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1];
378 int i;
379
380 for (i = 0; i < FSCRYPT_KEY_IDENTIFIER_SIZE; i++)
381 sprintf(&buf[2 * i], "%02x", master_key_identifier[i]);
382
383 return buf;
384}
385
a7a5e44c
EB
386static const char *
387keyspectype(const struct fscrypt_key_specifier *key_spec)
388{
389 switch (key_spec->type) {
390 case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
391 return _("descriptor");
392 case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
393 return _("identifier");
394 }
395 return _("[unknown]");
396}
397
398static const char *
399keyspec2str(const struct fscrypt_key_specifier *key_spec)
400{
401 switch (key_spec->type) {
402 case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
403 return keydesc2str(key_spec->u.descriptor);
404 case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
405 return keyid2str(key_spec->u.identifier);
406 }
407 return _("[unknown]");
408}
409
410static bool
411str2keydesc(const char *str,
412 __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE])
413{
414 if (!hex2bin(str, master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE)) {
415 fprintf(stderr, _("invalid key descriptor: %s\n"), str);
416 return false;
417 }
418 return true;
419}
420
421static bool
422str2keyid(const char *str,
423 __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
424{
425 if (!hex2bin(str, master_key_identifier, FSCRYPT_KEY_IDENTIFIER_SIZE)) {
426 fprintf(stderr, _("invalid key identifier: %s\n"), str);
427 return false;
428 }
429 return true;
430}
431
432/*
433 * Parse a key specifier (descriptor or identifier) given as a hex string.
434 *
435 * 8 bytes (16 hex chars) == key descriptor == v1 encryption policy.
436 * 16 bytes (32 hex chars) == key identifier == v2 encryption policy.
437 *
438 * If a policy_version is given (>= 0), then the corresponding type of key
439 * specifier is required. Otherwise the specifier type and policy_version are
440 * determined based on the length of the given hex string.
441 *
442 * Returns the policy version, or -1 on error.
443 */
444static int
445str2keyspec(const char *str, int policy_version,
446 struct fscrypt_key_specifier *key_spec)
447{
448 if (policy_version < 0) { /* version unspecified? */
449 size_t len = strlen(str);
450
451 if (len == 2 * FSCRYPT_KEY_DESCRIPTOR_SIZE) {
452 policy_version = FSCRYPT_POLICY_V1;
453 } else if (len == 2 * FSCRYPT_KEY_IDENTIFIER_SIZE) {
454 policy_version = FSCRYPT_POLICY_V2;
455 } else {
456 fprintf(stderr, _("invalid key specifier: %s\n"), str);
457 return -1;
458 }
459 }
460 if (policy_version == FSCRYPT_POLICY_V2) {
461 if (!str2keyid(str, key_spec->u.identifier))
462 return -1;
463 key_spec->type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
464 } else {
465 if (!str2keydesc(str, key_spec->u.descriptor))
466 return -1;
467 key_spec->type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
468 }
469 return policy_version;
470}
471
dfe209d8
EB
472static int
473parse_key_id(const char *arg)
474{
475 long value;
476 char *tmp;
477
478 value = strtol(arg, &tmp, 0);
479 if (value <= 0 || value > INT_MAX || tmp == arg || *tmp != '\0') {
480 fprintf(stderr, _("invalid key ID: %s\n"), arg);
481 /* 0 is never a valid Linux key ID. */
482 return 0;
483 }
484 return value;
485}
486
c304c84f
EB
487static void
488test_for_v2_policy_support(void)
489{
490 struct fscrypt_get_policy_ex_arg arg;
491
492 arg.policy_size = sizeof(arg.policy);
493
494 if (ioctl(file->fd, FS_IOC_GET_ENCRYPTION_POLICY_EX, &arg) == 0 ||
495 errno == ENODATA /* file unencrypted */) {
496 printf(_("supported\n"));
497 return;
498 }
499 if (errno == ENOTTY) {
500 printf(_("unsupported\n"));
501 return;
502 }
503 fprintf(stderr,
504 _("%s: unexpected error checking for FS_IOC_GET_ENCRYPTION_POLICY_EX support: %s\n"),
505 file->name, strerror(errno));
506 exitcode = 1;
507}
508
509static void
510show_v1_encryption_policy(const struct fscrypt_policy_v1 *policy)
511{
512 printf(_("Encryption policy for %s:\n"), file->name);
513 printf(_("\tPolicy version: %u\n"), policy->version);
514 printf(_("\tMaster key descriptor: %s\n"),
515 keydesc2str(policy->master_key_descriptor));
516 printf(_("\tContents encryption mode: %u (%s)\n"),
517 policy->contents_encryption_mode,
518 mode2str(policy->contents_encryption_mode));
519 printf(_("\tFilenames encryption mode: %u (%s)\n"),
520 policy->filenames_encryption_mode,
521 mode2str(policy->filenames_encryption_mode));
522 printf(_("\tFlags: 0x%02x\n"), policy->flags);
523}
524
525static void
526show_v2_encryption_policy(const struct fscrypt_policy_v2 *policy)
527{
528 printf(_("Encryption policy for %s:\n"), file->name);
529 printf(_("\tPolicy version: %u\n"), policy->version);
530 printf(_("\tMaster key identifier: %s\n"),
531 keyid2str(policy->master_key_identifier));
532 printf(_("\tContents encryption mode: %u (%s)\n"),
533 policy->contents_encryption_mode,
534 mode2str(policy->contents_encryption_mode));
535 printf(_("\tFilenames encryption mode: %u (%s)\n"),
536 policy->filenames_encryption_mode,
537 mode2str(policy->filenames_encryption_mode));
538 printf(_("\tFlags: 0x%02x\n"), policy->flags);
539}
540
0cf66b0f
EB
541static int
542get_encpolicy_f(int argc, char **argv)
543{
c304c84f
EB
544 int c;
545 struct fscrypt_get_policy_ex_arg arg;
546 bool only_use_v1_ioctl = false;
547 int res;
548
549 while ((c = getopt(argc, argv, "1t")) != EOF) {
550 switch (c) {
551 case '1':
552 only_use_v1_ioctl = true;
553 break;
554 case 't':
555 test_for_v2_policy_support();
556 return 0;
557 default:
558 return command_usage(&get_encpolicy_cmd);
559 }
560 }
561 argc -= optind;
562 argv += optind;
563
564 if (argc != 0)
565 return command_usage(&get_encpolicy_cmd);
566
567 /* first try the new ioctl */
568 if (only_use_v1_ioctl) {
569 res = -1;
570 errno = ENOTTY;
571 } else {
572 arg.policy_size = sizeof(arg.policy);
573 res = ioctl(file->fd, FS_IOC_GET_ENCRYPTION_POLICY_EX, &arg);
574 }
575
576 /* fall back to the old ioctl */
577 if (res != 0 && errno == ENOTTY)
578 res = ioctl(file->fd, FS_IOC_GET_ENCRYPTION_POLICY,
579 &arg.policy.v1);
0cf66b0f 580
c304c84f
EB
581 if (res != 0) {
582 fprintf(stderr, _("%s: failed to get encryption policy: %s\n"),
0cf66b0f
EB
583 file->name, strerror(errno));
584 exitcode = 1;
585 return 0;
586 }
587
c304c84f
EB
588 switch (arg.policy.version) {
589 case FSCRYPT_POLICY_V1:
590 show_v1_encryption_policy(&arg.policy.v1);
591 break;
592 case FSCRYPT_POLICY_V2:
593 show_v2_encryption_policy(&arg.policy.v2);
594 break;
595 default:
596 printf(_("Encryption policy for %s:\n"), file->name);
597 printf(_("\tPolicy version: %u (unknown)\n"),
598 arg.policy.version);
599 break;
600 }
0cf66b0f
EB
601 return 0;
602}
603
604static int
605set_encpolicy_f(int argc, char **argv)
606{
607 int c;
a7a5e44c
EB
608 __u8 contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
609 __u8 filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
610 __u8 flags = FSCRYPT_POLICY_FLAGS_PAD_16;
e97caf71 611 __u8 log2_data_unit_size = 0;
a7a5e44c
EB
612 int version = -1; /* unspecified */
613 struct fscrypt_key_specifier key_spec;
614 union {
615 __u8 version;
616 struct fscrypt_policy_v1 v1;
617 struct fscrypt_policy_v2 v2;
618 } policy;
0cf66b0f 619
e97caf71 620 while ((c = getopt(argc, argv, "c:n:f:s:v:")) != EOF) {
0cf66b0f
EB
621 switch (c) {
622 case 'c':
a7a5e44c
EB
623 if (!parse_mode(optarg, &contents_encryption_mode)) {
624 fprintf(stderr,
625 _("invalid contents encryption mode: %s\n"),
626 optarg);
9e1595e6 627 exitcode = 1;
0cf66b0f
EB
628 return 0;
629 }
630 break;
631 case 'n':
a7a5e44c
EB
632 if (!parse_mode(optarg, &filenames_encryption_mode)) {
633 fprintf(stderr,
634 _("invalid filenames encryption mode: %s\n"),
635 optarg);
9e1595e6 636 exitcode = 1;
0cf66b0f
EB
637 return 0;
638 }
639 break;
640 case 'f':
a7a5e44c
EB
641 if (!parse_byte_value(optarg, &flags)) {
642 fprintf(stderr, _("invalid flags: %s\n"),
643 optarg);
9e1595e6 644 exitcode = 1;
0cf66b0f
EB
645 return 0;
646 }
647 break;
e97caf71
EB
648 case 's':
649 if (!parse_byte_value(optarg, &log2_data_unit_size)) {
650 fprintf(stderr, _("invalid log2_dusize: %s\n"),
651 optarg);
652 exitcode = 1;
653 return 0;
654 }
655 break;
a7a5e44c
EB
656 case 'v': {
657 __u8 val;
658
659 if (!parse_byte_value(optarg, &val)) {
660 fprintf(stderr,
661 _("invalid policy version: %s\n"),
0cf66b0f 662 optarg);
9e1595e6 663 exitcode = 1;
0cf66b0f
EB
664 return 0;
665 }
a7a5e44c
EB
666 if (val == 1) /* Just to avoid annoying people... */
667 val = FSCRYPT_POLICY_V1;
668 version = val;
0cf66b0f 669 break;
a7a5e44c 670 }
0cf66b0f 671 default:
9e1595e6 672 exitcode = 1;
0cf66b0f
EB
673 return command_usage(&set_encpolicy_cmd);
674 }
675 }
676 argc -= optind;
677 argv += optind;
678
9e1595e6
DC
679 if (argc > 1) {
680 exitcode = 1;
0cf66b0f 681 return command_usage(&set_encpolicy_cmd);
9e1595e6 682 }
0cf66b0f 683
a7a5e44c
EB
684 /*
685 * If unspecified, the key descriptor or identifier defaults to all 0's.
686 * If the policy version is additionally unspecified, it defaults to v1.
687 */
688 memset(&key_spec, 0, sizeof(key_spec));
0cf66b0f 689 if (argc > 0) {
a7a5e44c 690 version = str2keyspec(argv[0], version, &key_spec);
9e1595e6
DC
691 if (version < 0) {
692 exitcode = 1;
0cf66b0f 693 return 0;
9e1595e6 694 }
a7a5e44c
EB
695 }
696 if (version < 0) /* version unspecified? */
697 version = FSCRYPT_POLICY_V1;
0cf66b0f 698
a7a5e44c
EB
699 memset(&policy, 0, sizeof(policy));
700 policy.version = version;
701 if (version == FSCRYPT_POLICY_V2) {
702 policy.v2.contents_encryption_mode = contents_encryption_mode;
703 policy.v2.filenames_encryption_mode = filenames_encryption_mode;
704 policy.v2.flags = flags;
e97caf71 705 policy.v2.log2_data_unit_size = log2_data_unit_size;
a7a5e44c
EB
706 memcpy(policy.v2.master_key_identifier, key_spec.u.identifier,
707 FSCRYPT_KEY_IDENTIFIER_SIZE);
708 } else {
e97caf71
EB
709 if (log2_data_unit_size != 0) {
710 fprintf(stderr,
711 "v1 policy does not support selecting the data unit size\n");
712 exitcode = 1;
713 return 0;
714 }
a7a5e44c
EB
715 /*
716 * xfstests passes .version = 255 for testing. Just use
717 * 'struct fscrypt_policy_v1' for both v1 and unknown versions.
718 */
719 policy.v1.contents_encryption_mode = contents_encryption_mode;
720 policy.v1.filenames_encryption_mode = filenames_encryption_mode;
721 policy.v1.flags = flags;
722 memcpy(policy.v1.master_key_descriptor, key_spec.u.descriptor,
723 FSCRYPT_KEY_DESCRIPTOR_SIZE);
0cf66b0f
EB
724 }
725
a7a5e44c
EB
726 if (ioctl(file->fd, FS_IOC_SET_ENCRYPTION_POLICY, &policy) != 0) {
727 fprintf(stderr, _("%s: failed to set encryption policy: %s\n"),
0cf66b0f
EB
728 file->name, strerror(errno));
729 exitcode = 1;
0cf66b0f 730 }
0cf66b0f
EB
731 return 0;
732}
733
ba71de04
EB
734static ssize_t
735read_until_limit_or_eof(int fd, void *buf, size_t limit)
736{
737 size_t bytes_read = 0;
738 ssize_t res;
739
740 while (limit) {
741 res = read(fd, buf, limit);
742 if (res < 0)
743 return res;
744 if (res == 0)
745 break;
746 buf += res;
747 bytes_read += res;
748 limit -= res;
749 }
750 return bytes_read;
751}
752
753static int
754add_enckey_f(int argc, char **argv)
755{
756 int c;
757 struct fscrypt_add_key_arg *arg;
758 ssize_t raw_size;
4aaa3af1 759 int retval = 0;
ba71de04
EB
760
761 arg = calloc(1, sizeof(*arg) + FSCRYPT_MAX_KEY_SIZE + 1);
762 if (!arg) {
763 perror("calloc");
764 exitcode = 1;
765 return 0;
766 }
767
768 arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
769
dfe209d8 770 while ((c = getopt(argc, argv, "d:k:")) != EOF) {
ba71de04
EB
771 switch (c) {
772 case 'd':
773 arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
774 if (!str2keydesc(optarg, arg->key_spec.u.descriptor))
775 goto out;
776 break;
dfe209d8
EB
777 case 'k':
778 arg->key_id = parse_key_id(optarg);
779 if (arg->key_id == 0)
780 goto out;
781 break;
ba71de04 782 default:
9e1595e6 783 exitcode = 1;
4aaa3af1
ES
784 retval = command_usage(&add_enckey_cmd);
785 goto out;
ba71de04
EB
786 }
787 }
788 argc -= optind;
789 argv += optind;
790
4aaa3af1 791 if (argc != 0) {
9e1595e6 792 exitcode = 1;
4aaa3af1
ES
793 retval = command_usage(&add_enckey_cmd);
794 goto out;
795 }
ba71de04 796
dfe209d8
EB
797 if (arg->key_id == 0) {
798 raw_size = read_until_limit_or_eof(STDIN_FILENO, arg->raw,
799 FSCRYPT_MAX_KEY_SIZE + 1);
800 if (raw_size < 0) {
801 fprintf(stderr, _("Error reading key from stdin: %s\n"),
802 strerror(errno));
803 exitcode = 1;
804 goto out;
805 }
806 if (raw_size > FSCRYPT_MAX_KEY_SIZE) {
807 fprintf(stderr,
808 _("Invalid key; got > FSCRYPT_MAX_KEY_SIZE (%d) bytes on stdin!\n"),
809 FSCRYPT_MAX_KEY_SIZE);
9e1595e6 810 exitcode = 1;
dfe209d8
EB
811 goto out;
812 }
813 arg->raw_size = raw_size;
814 } /* else, raw key is given via key with ID 'key_id' */
ba71de04
EB
815
816 if (ioctl(file->fd, FS_IOC_ADD_ENCRYPTION_KEY, arg) != 0) {
817 fprintf(stderr, _("Error adding encryption key: %s\n"),
818 strerror(errno));
819 exitcode = 1;
820 goto out;
821 }
822 printf(_("Added encryption key with %s %s\n"),
823 keyspectype(&arg->key_spec), keyspec2str(&arg->key_spec));
824out:
825 memset(arg->raw, 0, FSCRYPT_MAX_KEY_SIZE + 1);
826 free(arg);
4aaa3af1 827 return retval;
ba71de04
EB
828}
829
c808a097
EB
830static int
831rm_enckey_f(int argc, char **argv)
832{
833 int c;
834 struct fscrypt_remove_key_arg arg;
835 int ioc = FS_IOC_REMOVE_ENCRYPTION_KEY;
836
837 memset(&arg, 0, sizeof(arg));
838
839 while ((c = getopt(argc, argv, "a")) != EOF) {
840 switch (c) {
841 case 'a':
842 ioc = FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS;
843 break;
844 default:
9e1595e6 845 exitcode = 1;
c808a097
EB
846 return command_usage(&rm_enckey_cmd);
847 }
848 }
849 argc -= optind;
850 argv += optind;
851
9e1595e6
DC
852 if (argc != 1) {
853 exitcode = 1;
c808a097 854 return command_usage(&rm_enckey_cmd);
9e1595e6 855 }
c808a097 856
9e1595e6
DC
857 if (str2keyspec(argv[0], -1, &arg.key_spec) < 0) {
858 exitcode = 1;
c808a097 859 return 0;
9e1595e6 860 }
c808a097
EB
861
862 if (ioctl(file->fd, ioc, &arg) != 0) {
863 fprintf(stderr, _("Error removing encryption key: %s\n"),
864 strerror(errno));
865 exitcode = 1;
866 return 0;
867 }
868 if (arg.removal_status_flags &
869 FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS) {
870 printf(_("Removed user's claim to encryption key with %s %s\n"),
871 keyspectype(&arg.key_spec), keyspec2str(&arg.key_spec));
872 } else if (arg.removal_status_flags &
873 FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY) {
874 printf(_("Removed encryption key with %s %s, but files still busy\n"),
875 keyspectype(&arg.key_spec), keyspec2str(&arg.key_spec));
876 } else {
877 printf(_("Removed encryption key with %s %s\n"),
878 keyspectype(&arg.key_spec), keyspec2str(&arg.key_spec));
879 }
880 return 0;
881}
882
dafb55f9
EB
883static int
884enckey_status_f(int argc, char **argv)
885{
886 struct fscrypt_get_key_status_arg arg;
887
888 memset(&arg, 0, sizeof(arg));
889
9e1595e6
DC
890 if (str2keyspec(argv[1], -1, &arg.key_spec) < 0) {
891 exitcode = 1;
dafb55f9 892 return 0;
9e1595e6 893 }
dafb55f9
EB
894
895 if (ioctl(file->fd, FS_IOC_GET_ENCRYPTION_KEY_STATUS, &arg) != 0) {
896 fprintf(stderr, _("Error getting encryption key status: %s\n"),
897 strerror(errno));
898 exitcode = 1;
899 return 0;
900 }
901
902 switch (arg.status) {
903 case FSCRYPT_KEY_STATUS_PRESENT:
904 printf(_("Present"));
905 if (arg.user_count || arg.status_flags) {
906 printf(" (user_count=%u", arg.user_count);
907 if (arg.status_flags &
908 FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF)
909 printf(", added_by_self");
910 arg.status_flags &=
911 ~FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF;
912 if (arg.status_flags)
913 printf(", unknown_flags=0x%08x",
914 arg.status_flags);
915 printf(")");
916 }
917 printf("\n");
918 return 0;
919 case FSCRYPT_KEY_STATUS_ABSENT:
920 printf(_("Absent\n"));
921 return 0;
922 case FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED:
923 printf(_("Incompletely removed\n"));
924 return 0;
925 default:
926 printf(_("Unknown status (%u)\n"), arg.status);
927 return 0;
928 }
929}
930
0cf66b0f
EB
931void
932encrypt_init(void)
933{
934 get_encpolicy_cmd.name = "get_encpolicy";
935 get_encpolicy_cmd.cfunc = get_encpolicy_f;
c304c84f 936 get_encpolicy_cmd.args = _("[-1] [-t]");
0cf66b0f 937 get_encpolicy_cmd.argmin = 0;
c304c84f 938 get_encpolicy_cmd.argmax = -1;
0cf66b0f
EB
939 get_encpolicy_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
940 get_encpolicy_cmd.oneline =
941 _("display the encryption policy of the current file");
c304c84f 942 get_encpolicy_cmd.help = get_encpolicy_help;
0cf66b0f
EB
943
944 set_encpolicy_cmd.name = "set_encpolicy";
945 set_encpolicy_cmd.cfunc = set_encpolicy_f;
946 set_encpolicy_cmd.args =
e97caf71 947 _("[-c mode] [-n mode] [-f flags] [-s log2_dusize] [-v version] [keyspec]");
0cf66b0f
EB
948 set_encpolicy_cmd.argmin = 0;
949 set_encpolicy_cmd.argmax = -1;
950 set_encpolicy_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
951 set_encpolicy_cmd.oneline =
952 _("assign an encryption policy to the current file");
953 set_encpolicy_cmd.help = set_encpolicy_help;
954
ba71de04
EB
955 add_enckey_cmd.name = "add_enckey";
956 add_enckey_cmd.cfunc = add_enckey_f;
dfe209d8 957 add_enckey_cmd.args = _("[-d descriptor] [-k key_id]");
ba71de04
EB
958 add_enckey_cmd.argmin = 0;
959 add_enckey_cmd.argmax = -1;
960 add_enckey_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
961 add_enckey_cmd.oneline = _("add an encryption key to the filesystem");
962 add_enckey_cmd.help = add_enckey_help;
963
c808a097
EB
964 rm_enckey_cmd.name = "rm_enckey";
965 rm_enckey_cmd.cfunc = rm_enckey_f;
966 rm_enckey_cmd.args = _("[-a] keyspec");
967 rm_enckey_cmd.argmin = 0;
968 rm_enckey_cmd.argmax = -1;
969 rm_enckey_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
970 rm_enckey_cmd.oneline =
971 _("remove an encryption key from the filesystem");
972 rm_enckey_cmd.help = rm_enckey_help;
973
dafb55f9
EB
974 enckey_status_cmd.name = "enckey_status";
975 enckey_status_cmd.cfunc = enckey_status_f;
976 enckey_status_cmd.args = _("keyspec");
977 enckey_status_cmd.argmin = 1;
978 enckey_status_cmd.argmax = 1;
979 enckey_status_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
980 enckey_status_cmd.oneline =
981 _("get the status of a filesystem encryption key");
982 enckey_status_cmd.help = enckey_status_help;
983
0cf66b0f
EB
984 add_command(&get_encpolicy_cmd);
985 add_command(&set_encpolicy_cmd);
ba71de04 986 add_command(&add_enckey_cmd);
c808a097 987 add_command(&rm_enckey_cmd);
dafb55f9 988 add_command(&enckey_status_cmd);
0cf66b0f 989}