Skip to content

Commit bace9a0

Browse files
committed
fscryptctl: add support for encrypted and trusted keys
For both v1 and v2 key setup mechanisms, userspace supplies the raw key material to the kernel after which it is never again disclosed to userspace. Use of encrypted and trusted keys offers stronger guarantees: The key material is generated with the kernel and is never disclosed to userspace in clear text and, in the case of trusted keys, can be directly rooted to a trust source like a TPM chip. Support for using encrypted and trusted keys is not yet mainline. This draft PR is meant to be illustrative. It will be finalized should the fscrypt encrypted/trusted key extension be merged. Signed-off-by: Ahmad Fatoum <[email protected]>
1 parent e863642 commit bace9a0

File tree

4 files changed

+64
-9
lines changed

4 files changed

+64
-9
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,17 @@ tips](https://github.com/google/fscrypt#getting-encryption-not-enabled-on-an-ext
7474
For full usage details, see the manual page (`man fscryptctl`), or alternatively
7575
run `fscryptctl --help`.
7676

77-
The `add_key` command accepts the encryption key in binary on standard input.
77+
The `add_key` command, by default, accepts the encryption key in binary on
78+
standard input.
7879
It is critical that this be a real cryptographic key (and not a passphrase, for
7980
example), since `fscryptctl` doesn't do key stretching itself. Obviously, don't
8081
store the raw encryption key alongside the encrypted files. (If you need
8182
support for passphrases, use `fscrypt` instead of `fscryptctl`.)
8283

84+
Alternatively, `add_key --description=$desc` will instruct the kernel to
85+
extract the kernel material from an existing encrypted or trusted key with
86+
the description `$desc`.
87+
8388
After running the `add_key` command to add an encryption key to a filesystem,
8489
you can use the `set_policy` command to create an encrypted directory on that
8590
filesystem. The encryption key is specified by the 32-character hex "key

fscrypt_uapi.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,26 @@ struct fscrypt_provisioning_key_payload {
120120
__u8 raw[];
121121
};
122122

123+
/*
124+
* fscrypt_add_key_arg::raw contains the raw key material directly
125+
* if key_id == 0
126+
*/
127+
#define FSCRYPT_KEY_ADD_RAW_ASIS 0
128+
129+
/*
130+
* fscrypt_add_key_arg::raw is a key descriptor for an already
131+
* existing kernel encrypted or trusted key if key_id == 0.
132+
* The kernel key's material will be used as input for fscrypt.
133+
*/
134+
#define FSCRYPT_KEY_ADD_RAW_DESC 1
135+
123136
/* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */
124137
struct fscrypt_add_key_arg {
125138
struct fscrypt_key_specifier key_spec;
126139
__u32 raw_size;
127140
__u32 key_id;
128-
__u32 __reserved[8];
141+
__u32 raw_flags; /* one of FSCRYPT_KEY_ADD_RAW_* */
142+
__u32 __reserved[7];
129143
__u8 raw[];
130144
};
131145

fscryptctl.1.md

Lines changed: 7 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,12 @@ 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+
**\-\-description**=*DESCRIPTION*
60+
: Don't read raw key material from standard input. Instead, instruct the
61+
kernel to extract key material from an existing encrypted or trusted
62+
key with the supplied *DESCRIPTION*.
5863

5964
## **fscryptctl remove_key** [*OPTION*...] *KEY_IDENTIFIER* *MOUNTPOINT*
6065

fscryptctl.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ static void secure_wipe(void *v, size_t n) {
6565
#define FSCRYPT_KEY_DESCRIPTOR_HEX_SIZE ((2 * FSCRYPT_KEY_DESCRIPTOR_SIZE) + 1)
6666
#define FSCRYPT_KEY_IDENTIFIER_HEX_SIZE ((2 * FSCRYPT_KEY_IDENTIFIER_SIZE) + 1)
6767

68+
#define FSCRYPT_RAW_MAX_SIZE 4096 // max(KEY_MAX_DESC_SIZE, FSCRYPT_MAX_KEY_SIZE)
69+
6870
// Human-readable strings for encryption modes, indexed by the encryption mode
6971
static const char *const mode_strings[] = {
7072
[FSCRYPT_MODE_AES_256_XTS] = "AES-256-XTS",
@@ -78,6 +80,7 @@ static const char *const mode_strings[] = {
7880
static const int padding_values[] = {4, 8, 16, 32};
7981

8082
enum {
83+
OPT_KEY_DESCRIPTION,
8184
OPT_ALL_USERS,
8285
OPT_CONTENTS,
8386
OPT_DIRECT_KEY,
@@ -94,8 +97,9 @@ static void __attribute__((__noreturn__)) usage(FILE *out) {
9497
" fscryptctl <command> [arguments] [options]\n"
9598
"\nCommands:\n"
9699
" fscryptctl add_key <mountpoint>\n"
97-
" Read a key from stdin, add it to the specified mounted filesystem,\n"
98-
" and print its identifier.\n"
100+
" Add a key add to the specified mounted filesystem and print its\n"
101+
" identifier. Raw key is read from stdin by default or is taken\n"
102+
" from the payload of a kernel trusted or encrypted key\n"
99103
" fscryptctl remove_key <key identifier> <mountpoint>\n"
100104
" Remove the key with the specified identifier from the specified\n"
101105
" mounted filesystem.\n"
@@ -112,6 +116,10 @@ static void __attribute__((__noreturn__)) usage(FILE *out) {
112116
" print this help screen\n"
113117
" -v, --version\n"
114118
" print the version of fscrypt\n"
119+
" add_key\n"
120+
" --description=<trusted-or-encrypted-key>\n"
121+
" Instead of reading raw key material over stdin, use the\n"
122+
" payload of an already existing encrypted or trusted key.\n"
115123
" remove_key\n"
116124
" --all-users\n"
117125
" force-remove all users' claims to the key (requires root)\n"
@@ -372,22 +380,45 @@ static bool set_policy(const char *path,
372380
// -----------------------------------------------------------------------------
373381

374382
static int cmd_add_key(int argc, char *const argv[]) {
375-
handle_no_options(&argc, &argv);
383+
const char *desc = NULL;
384+
385+
static const struct option add_key_options[] = {
386+
{"description", required_argument, NULL, OPT_KEY_DESCRIPTION}, {NULL, 0, NULL, 0}};
387+
388+
int ch;
389+
while ((ch = getopt_long(argc, argv, "", add_key_options, NULL)) != -1) {
390+
switch (ch) {
391+
case OPT_KEY_DESCRIPTION:
392+
desc = optarg;
393+
break;
394+
default:
395+
usage(stderr);
396+
}
397+
}
398+
argc -= optind;
399+
argv += optind;
376400
if (argc != 1) {
377401
fputs("error: must specify a single mountpoint\n", stderr);
378402
return EXIT_FAILURE;
379403
}
380404
const char *mountpoint = argv[0];
381405

382406
struct fscrypt_add_key_arg *arg =
383-
calloc(sizeof(*arg) + FSCRYPT_MAX_KEY_SIZE, 1);
407+
calloc(sizeof(*arg) + FSCRYPT_RAW_MAX_SIZE, 1);
384408
if (!arg) {
385409
fputs("error: failed to allocate memory\n", stderr);
386410
return EXIT_FAILURE;
387411
}
388412

389413
int status = EXIT_FAILURE;
390-
arg->raw_size = read_key(arg->raw);
414+
if (desc) {
415+
arg->raw_flags = FSCRYPT_KEY_ADD_RAW_DESC;
416+
arg->raw_size = strlen(desc);
417+
memcpy(arg->raw, desc, arg->raw_size);
418+
} else {
419+
arg->raw_flags = FSCRYPT_KEY_ADD_RAW_ASIS;
420+
arg->raw_size = read_key(arg->raw);
421+
}
391422
if (arg->raw_size == 0) {
392423
goto cleanup;
393424
}

0 commit comments

Comments
 (0)