Skip to content

Commit e9ef440

Browse files
committed
Add support for adding hardware-wrapped keys
Update the 'fscryptctl add_key' command to accept hardware-wrapped keys. Previously, it only accepted raw keys. This relies on the support for FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED which is available in Linux 6.16 and later. For more details, see the Linux kernel commit https://git.kernel.org/linus/c07d3aede2b26830
1 parent d6f2db5 commit e9ef440

3 files changed

Lines changed: 43 additions & 9 deletions

File tree

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# fscryptctl release notes
22

3+
## Version 1.3.0
4+
5+
* `fscryptctl add_key` now supports the `--hw-wrapped-key` option.
6+
37
## Version 1.2.0
48

59
* `fscryptctl set_policy` now accepts the `--data-unit-size` option.

fscryptctl.1.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ feature, see the references at the end of this page.
4040

4141
# SUBCOMMANDS
4242

43-
## **fscryptctl add_key** *MOUNTPOINT*
43+
## **fscryptctl add_key** [*OPTION*...] *MOUNTPOINT*
4444

4545
Add an encryption key to the given mounted filesystem. This will "unlock" any
4646
files and directories that are protected by the given key on the given
@@ -54,7 +54,11 @@ If successful, **fscryptctl add_key** will print the key identifier of the newly
5454
added key; this will be a 32-character hex string which can be passed to other
5555
**fscryptctl** commands.
5656

57-
**fscryptctl add_key** does not accept any options.
57+
Options accepted by **fscryptctl add_key**:
58+
59+
**\-\-hw\-wrapped\-key**
60+
: Add a hardware-wrapped key. If this option is given, the key must be a
61+
hardware-wrapped key in ephemerally-wrapped form, rather than a raw key.
5862

5963
## **fscryptctl remove_key** [*OPTION*...] *KEY_IDENTIFIER* *MOUNTPOINT*
6064

fscryptctl.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
#define VERSION "v1.2.0"
4242
#endif
4343

44+
// This matches the limit used by the kernel internally as of Linux 6.16. There
45+
// isn't much reason to think that a wrapped key would ever be larger than this,
46+
// but it can be increased if ever needed.
47+
#define MAX_WRAPPED_KEY_SIZE 128
48+
4449
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
4550

4651
static void *xzalloc(size_t size) {
@@ -103,6 +108,7 @@ enum {
103108
OPT_DATA_UNIT_SIZE,
104109
OPT_DIRECT_KEY,
105110
OPT_FILENAMES,
111+
OPT_HW_WRAPPED_KEY,
106112
OPT_IV_INO_LBLK_32,
107113
OPT_IV_INO_LBLK_64,
108114
OPT_PADDING,
@@ -133,6 +139,9 @@ static void __attribute__((__noreturn__)) usage(FILE *out) {
133139
" print this help screen\n"
134140
" -v, --version\n"
135141
" print the version of fscryptctl\n"
142+
" add_key\n"
143+
" --hw-wrapped-key\n"
144+
" add a hardware-wrapped key (rather than a raw key)\n"
136145
" remove_key\n"
137146
" --all-users\n"
138147
" force-remove all users' claims to the key (requires root)\n"
@@ -154,7 +163,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out) {
154163
"\nNotes:\n"
155164
" Keys are identified by 32-character hex strings (key identifiers).\n"
156165
"\n"
157-
" Raw keys are given on stdin in binary and usually must be 64 bytes.\n"
166+
" Keys are given on stdin in raw binary.\n"
158167
"\n"
159168
" For more information, run `man fscryptctl`.\n",
160169
out);
@@ -420,20 +429,38 @@ static bool set_policy(const char *path,
420429
// -----------------------------------------------------------------------------
421430

422431
static int cmd_add_key(int argc, char *const argv[]) {
423-
handle_no_options(&argc, &argv);
432+
static const struct option add_key_options[] = {
433+
{"hw-wrapped-key", no_argument, NULL, OPT_HW_WRAPPED_KEY},
434+
{NULL, 0, NULL, 0}};
435+
int max_size = FSCRYPT_MAX_KEY_SIZE;
436+
__u32 flags = 0;
437+
438+
int ch;
439+
while ((ch = getopt_long(argc, argv, "", add_key_options, NULL)) != -1) {
440+
switch (ch) {
441+
case OPT_HW_WRAPPED_KEY:
442+
flags |= FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED;
443+
max_size = MAX_WRAPPED_KEY_SIZE;
444+
break;
445+
default:
446+
usage(stderr);
447+
}
448+
}
449+
argc -= optind;
450+
argv += optind;
424451
if (argc != 1) {
425452
fputs("error: must specify a single mountpoint\n", stderr);
426453
return EXIT_FAILURE;
427454
}
428455
const char *mountpoint = argv[0];
429456

430-
struct fscrypt_add_key_arg *arg =
431-
xzalloc(sizeof(*arg) + FSCRYPT_MAX_KEY_SIZE);
457+
struct fscrypt_add_key_arg *arg = xzalloc(sizeof(*arg) + max_size);
432458
int status = EXIT_FAILURE;
433-
arg->raw_size = read_key(arg->raw, FSCRYPT_MAX_KEY_SIZE);
459+
arg->raw_size = read_key(arg->raw, max_size);
434460
if (arg->raw_size == 0) {
435461
goto cleanup;
436462
}
463+
arg->flags = flags;
437464
arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
438465

439466
int fd = open(mountpoint, O_RDONLY | O_CLOEXEC);
@@ -455,8 +482,7 @@ static int cmd_add_key(int argc, char *const argv[]) {
455482
puts(identifier_hex);
456483
status = EXIT_SUCCESS;
457484
cleanup:
458-
secure_wipe(arg->raw, arg->raw_size);
459-
free(arg);
485+
wipe_and_free(arg, sizeof(*arg) + max_size);
460486
return status;
461487
}
462488

0 commit comments

Comments
 (0)