xref: /third_party/f2fs-tools/tools/f2fscrypt.c (revision 5e5c12b0)
1/*
2 * f2fscrypt.c - f2fs encryption management utility
3 *
4 * Authors: Kinglong Mee <kinglongmee@gmail.com>
5 *
6 * Copied from e4crypt that for ext4 filesystem.
7 * Authors: Michael Halcrow <mhalcrow@google.com>,
8 *	    Ildar Muslukhov <ildarm@google.com>
9 */
10
11#ifndef _LARGEFILE_SOURCE
12#define _LARGEFILE_SOURCE
13#endif
14
15#ifndef _LARGEFILE64_SOURCE
16#define _LARGEFILE64_SOURCE
17#endif
18
19#ifndef _GNU_SOURCE
20#define _GNU_SOURCE
21#endif
22
23#include <f2fs_fs.h>
24
25#include <assert.h>
26#include <errno.h>
27#include <getopt.h>
28#include <dirent.h>
29#include <errno.h>
30#include <stdarg.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#ifdef HAVE_MNTENT_H
35#include <mntent.h>
36#endif
37#include <sys/ioctl.h>
38#include <sys/stat.h>
39#include <sys/types.h>
40#include <fcntl.h>
41#include <termios.h>
42#include <unistd.h>
43#include <signal.h>
44#ifdef __KERNEL__
45#include <linux/fs.h>
46#endif
47
48#ifdef HAVE_UUID_UUID_H
49#include <uuid/uuid.h>
50#else
51typedef unsigned char uuid_t[16];
52#endif
53
54#if !defined(HAVE_ADD_KEY) || !defined(HAVE_KEYCTL)
55#include <sys/syscall.h>
56#endif
57#ifdef HAVE_SYS_KEY_H
58#include <sys/key.h>
59#endif
60
61#define F2FS_MAX_KEY_SIZE		64
62#define F2FS_MAX_PASSPHRASE_SIZE	1024
63#define F2FS_MAX_SALT_SIZE		256
64
65/* Encryption algorithms, key size and key reference len */
66#define F2FS_ENCRYPTION_MODE_INVALID		0
67#define F2FS_ENCRYPTION_MODE_AES_256_XTS	1
68#define F2FS_ENCRYPTION_MODE_AES_256_GCM	2
69#define F2FS_ENCRYPTION_MODE_AES_256_CBC	3
70#define F2FS_ENCRYPTION_MODE_AES_256_CTS	4
71
72#define F2FS_AES_256_XTS_KEY_SIZE		64
73#define F2FS_AES_256_GCM_KEY_SIZE		32
74#define F2FS_AES_256_CBC_KEY_SIZE		32
75#define F2FS_AES_256_CTS_KEY_SIZE		32
76#define F2FS_MAX_KEY_SIZE			64
77
78/* Password derivation constants */
79#define F2FS_MAX_PASSPHRASE_SIZE		1024
80#define F2FS_MAX_SALT_SIZE			256
81#define F2FS_PBKDF2_ITERATIONS			0xFFFF
82
83/* special process keyring shortcut IDs */
84#define KEY_SPEC_THREAD_KEYRING		-1
85#define KEY_SPEC_PROCESS_KEYRING	-2
86#define KEY_SPEC_SESSION_KEYRING	-3
87#define KEY_SPEC_USER_KEYRING		-4
88#define KEY_SPEC_USER_SESSION_KEYRING	-5
89#define KEY_SPEC_GROUP_KEYRING		-6
90
91#define KEYCTL_GET_KEYRING_ID		0
92#define KEYCTL_JOIN_SESSION_KEYRING	1
93#define KEYCTL_DESCRIBE			6
94#define KEYCTL_SEARCH			10
95#define KEYCTL_SESSION_TO_PARENT	18
96
97/*
98 * File system encryption support
99 */
100/* Policy provided via an ioctl on the topmost directory */
101#define F2FS_KEY_DESCRIPTOR_SIZE	8
102#define F2FS_KEY_REF_STR_BUF_SIZE ((F2FS_KEY_DESCRIPTOR_SIZE * 2) + 1)
103
104struct f2fs_fscrypt_policy {
105	__u8 version;
106	__u8 contents_encryption_mode;
107	__u8 filenames_encryption_mode;
108	__u8 flags;
109	__u8 master_key_descriptor[F2FS_KEY_DESCRIPTOR_SIZE];
110};
111
112static_assert(sizeof(struct f2fs_fscrypt_policy) == 12, "");
113
114#define F2FS_IOC_SET_ENCRYPTION_POLICY	_IOR('f', 19, struct f2fs_fscrypt_policy)
115#define F2FS_IOC_GET_ENCRYPTION_PWSALT	_IOW('f', 20, __u8[16])
116#define F2FS_IOC_GET_ENCRYPTION_POLICY	_IOW('f', 21, struct f2fs_fscrypt_policy)
117
118typedef int32_t key_serial_t;
119
120
121
122#define OPT_VERBOSE	0x0001
123#define OPT_QUIET	0x0002
124
125struct f2fs_encryption_key {
126        __u32 mode;
127        char raw[F2FS_MAX_KEY_SIZE];
128        __u32 size;
129};
130
131static_assert(sizeof(struct f2fs_encryption_key) == 72, "");
132
133int options;
134
135extern void f2fs_sha512(const unsigned char *in, unsigned long in_size,
136						unsigned char *out);
137
138#if !defined(HAVE_KEYCTL)
139static long keyctl(int cmd, ...)
140{
141	va_list va;
142	unsigned long arg2, arg3, arg4, arg5;
143
144	va_start(va, cmd);
145	arg2 = va_arg(va, unsigned long);
146	arg3 = va_arg(va, unsigned long);
147	arg4 = va_arg(va, unsigned long);
148	arg5 = va_arg(va, unsigned long);
149	va_end(va);
150	return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
151}
152#endif
153
154#if !defined(HAVE_ADD_KEY)
155static key_serial_t add_key(const char *type, const char *description,
156			    const void *payload, size_t plen,
157			    key_serial_t keyring)
158{
159	return syscall(__NR_add_key, type, description, payload,
160		       plen, keyring);
161}
162#endif
163
164static const unsigned char *hexchars = (const unsigned char *) "0123456789abcdef";
165static const size_t hexchars_size = 16;
166
167#define SHA512_LENGTH 64
168#define F2FS_KEY_TYPE_LOGON "logon"
169#define F2FS_KEY_DESC_PREFIX "f2fs:"
170#define F2FS_KEY_DESC_PREFIX_SIZE 5
171
172static int int_log2(int arg)
173{
174	int     l = 0;
175
176	arg >>= 1;
177	while (arg) {
178		l++;
179		arg >>= 1;
180	}
181	return l;
182}
183
184static void validate_paths(int argc, char *argv[], int path_start_index)
185{
186	int x;
187	int valid = 1;
188	struct stat st;
189
190	for (x = path_start_index; x < argc; x++) {
191		int ret = access(argv[x], W_OK);
192		if (ret) {
193		invalid:
194			perror(argv[x]);
195			valid = 0;
196			continue;
197		}
198		ret = stat(argv[x], &st);
199		if (ret < 0)
200			goto invalid;
201		if (!S_ISDIR(st.st_mode)) {
202			fprintf(stderr, "%s is not a directory\n", argv[x]);
203			goto invalid;
204		}
205	}
206	if (!valid)
207		exit(1);
208}
209
210static int hex2byte(const char *hex, size_t hex_size, unsigned char *bytes,
211		    size_t bytes_size)
212{
213	size_t x;
214	unsigned char *h, *l;
215
216	if (hex_size % 2)
217		return -EINVAL;
218	for (x = 0; x < hex_size; x += 2) {
219		h = memchr(hexchars, hex[x], hexchars_size);
220		if (!h)
221			return -EINVAL;
222		l = memchr(hexchars, hex[x + 1], hexchars_size);
223		if (!l)
224			return -EINVAL;
225		if ((x >> 1) >= bytes_size)
226			return -EINVAL;
227		bytes[x >> 1] = (((unsigned char)(h - hexchars) << 4) +
228				 (unsigned char)(l - hexchars));
229	}
230	return 0;
231}
232
233/*
234 * Salt handling
235 */
236struct salt {
237	unsigned char *salt;
238	char key_ref_str[F2FS_KEY_REF_STR_BUF_SIZE];
239	unsigned char key_desc[F2FS_KEY_DESCRIPTOR_SIZE];
240	unsigned char key[F2FS_MAX_KEY_SIZE];
241	size_t salt_len;
242};
243struct salt *salt_list;
244unsigned num_salt;
245unsigned max_salt;
246char in_passphrase[F2FS_MAX_PASSPHRASE_SIZE];
247
248static struct salt *find_by_salt(unsigned char *salt, size_t salt_len)
249{
250	unsigned int i;
251	struct salt *p;
252
253	for (i = 0, p = salt_list; i < num_salt; i++, p++)
254		if ((p->salt_len == salt_len) &&
255		    !memcmp(p->salt, salt, salt_len))
256			return p;
257	return NULL;
258}
259
260static void add_salt(unsigned char *salt, size_t salt_len)
261{
262	if (find_by_salt(salt, salt_len))
263		return;
264	if (num_salt >= max_salt) {
265		max_salt = num_salt + 10;
266		salt_list = realloc(salt_list, max_salt * sizeof(struct salt));
267		if (!salt_list) {
268			fprintf(stderr, "Couldn't allocate salt list\n");
269			exit(1);
270		}
271	}
272	salt_list[num_salt].salt = salt;
273	salt_list[num_salt].salt_len = salt_len;
274	num_salt++;
275}
276
277static void clear_secrets(void)
278{
279	if (salt_list) {
280		memset(salt_list, 0, sizeof(struct salt) * max_salt);
281		free(salt_list);
282		salt_list = NULL;
283	}
284	memset(in_passphrase, 0, sizeof(in_passphrase));
285}
286
287static void die_signal_handler(int UNUSED(signum),
288		siginfo_t *UNUSED(siginfo), void *UNUSED(context))
289{
290	clear_secrets();
291	exit(-1);
292}
293
294static void sigcatcher_setup(void)
295{
296	struct sigaction	sa;
297
298	memset(&sa, 0, sizeof(struct sigaction));
299	sa.sa_sigaction = die_signal_handler;
300	sa.sa_flags = SA_SIGINFO;
301
302	sigaction(SIGHUP, &sa, 0);
303	sigaction(SIGINT, &sa, 0);
304	sigaction(SIGQUIT, &sa, 0);
305	sigaction(SIGFPE, &sa, 0);
306	sigaction(SIGILL, &sa, 0);
307	sigaction(SIGBUS, &sa, 0);
308	sigaction(SIGSEGV, &sa, 0);
309	sigaction(SIGABRT, &sa, 0);
310	sigaction(SIGPIPE, &sa, 0);
311	sigaction(SIGALRM, &sa, 0);
312	sigaction(SIGTERM, &sa, 0);
313	sigaction(SIGUSR1, &sa, 0);
314	sigaction(SIGUSR2, &sa, 0);
315	sigaction(SIGPOLL, &sa, 0);
316	sigaction(SIGPROF, &sa, 0);
317	sigaction(SIGSYS, &sa, 0);
318	sigaction(SIGTRAP, &sa, 0);
319	sigaction(SIGVTALRM, &sa, 0);
320	sigaction(SIGXCPU, &sa, 0);
321	sigaction(SIGXFSZ, &sa, 0);
322}
323
324
325#define PARSE_FLAGS_NOTSUPP_OK	0x0001
326#define PARSE_FLAGS_FORCE_FN	0x0002
327
328static void parse_salt(char *salt_str, int flags)
329{
330	unsigned char buf[F2FS_MAX_SALT_SIZE];
331	char *cp = salt_str;
332	unsigned char *salt_buf;
333	int fd, ret, salt_len = 0;
334
335	if (flags & PARSE_FLAGS_FORCE_FN)
336		goto salt_from_filename;
337	if (strncmp(cp, "s:", 2) == 0) {
338		cp += 2;
339		salt_len = strlen(cp);
340		if (salt_len >= F2FS_MAX_SALT_SIZE)
341			goto invalid_salt;
342		strncpy((char *) buf, cp, sizeof(buf));
343	} else if (cp[0] == '/') {
344	salt_from_filename:
345		fd = open(cp, O_RDONLY | O_DIRECTORY);
346		if (fd == -1 && errno == ENOTDIR)
347			fd = open(cp, O_RDONLY);
348		if (fd == -1) {
349			perror(cp);
350			exit(1);
351		}
352		ret = ioctl(fd, F2FS_IOC_GET_ENCRYPTION_PWSALT, &buf);
353		close(fd);
354		if (ret < 0) {
355			if (flags & PARSE_FLAGS_NOTSUPP_OK)
356				return;
357			perror("F2FS_IOC_GET_ENCRYPTION_PWSALT");
358			exit(1);
359		}
360#ifdef HAVE_LIBUUID
361		if (options & OPT_VERBOSE) {
362			char tmp[80];
363			uuid_unparse(buf, tmp);
364			printf("%s has pw salt %s\n", cp, tmp);
365		}
366#endif
367		salt_len = 16;
368	} else if (strncmp(cp, "f:", 2) == 0) {
369		cp += 2;
370		goto salt_from_filename;
371	} else if (strncmp(cp, "0x", 2) == 0) {
372		unsigned char *h, *l;
373
374		cp += 2;
375		if (strlen(cp) & 1)
376			goto invalid_salt;
377		while (*cp) {
378			if (salt_len >= F2FS_MAX_SALT_SIZE)
379				goto invalid_salt;
380			h = memchr(hexchars, *cp++, hexchars_size);
381			l = memchr(hexchars, *cp++, hexchars_size);
382			if (!h || !l)
383				goto invalid_salt;
384			buf[salt_len++] =
385				(((unsigned char)(h - hexchars) << 4) +
386				 (unsigned char)(l - hexchars));
387		}
388#ifdef HAVE_LIBUUID
389	} else if (uuid_parse(cp, buf) == 0) {
390		salt_len = 16;
391#endif
392	} else {
393	invalid_salt:
394		fprintf(stderr, "Invalid salt: %s\n", salt_str);
395		exit(1);
396	}
397	salt_buf = malloc(salt_len);
398	if (!salt_buf) {
399		fprintf(stderr, "Couldn't allocate salt\n");
400		exit(1);
401	}
402	memcpy(salt_buf, buf, salt_len);
403	add_salt(salt_buf, salt_len);
404}
405
406static void set_policy(struct salt *set_salt, int pad,
407		       int argc, char *argv[], int path_start_index)
408{
409	struct salt *salt;
410	struct f2fs_fscrypt_policy policy;
411	uuid_t	uu;
412	int fd;
413	int x;
414	int rc;
415
416	if ((pad != 4) && (pad != 8) &&
417		 (pad != 16) && (pad != 32)) {
418		fprintf(stderr, "Invalid padding %d\n", pad);
419		exit(1);
420	}
421
422	for (x = path_start_index; x < argc; x++) {
423		fd = open(argv[x], O_DIRECTORY);
424		if (fd == -1) {
425			perror(argv[x]);
426			exit(1);
427		}
428		if (set_salt)
429			salt = set_salt;
430		else {
431			if (ioctl(fd, F2FS_IOC_GET_ENCRYPTION_PWSALT,
432				  &uu) < 0) {
433				perror("F2FS_IOC_GET_ENCRYPTION_PWSALT");
434				exit(1);
435			}
436			salt = find_by_salt(uu, sizeof(uu));
437			if (!salt) {
438				fprintf(stderr, "Couldn't find salt!?!\n");
439				exit(1);
440			}
441		}
442		policy.version = 0;
443		policy.contents_encryption_mode =
444			F2FS_ENCRYPTION_MODE_AES_256_XTS;
445		policy.filenames_encryption_mode =
446			F2FS_ENCRYPTION_MODE_AES_256_CTS;
447		policy.flags = int_log2(pad >> 2);
448		memcpy(policy.master_key_descriptor, salt->key_desc,
449		       F2FS_KEY_DESCRIPTOR_SIZE);
450		rc = ioctl(fd, F2FS_IOC_SET_ENCRYPTION_POLICY, &policy);
451		close(fd);
452		if (rc) {
453			printf("Error [%s] setting policy.\nThe key descriptor "
454			       "[%s] may not match the existing encryption "
455			       "context for directory [%s].\n",
456			       strerror(errno), salt->key_ref_str, argv[x]);
457			continue;
458		}
459		printf("Key with descriptor [%s] applied to %s.\n",
460		       salt->key_ref_str, argv[x]);
461	}
462}
463
464static void pbkdf2_sha512(const char *passphrase, struct salt *salt,
465			  unsigned int count,
466			  unsigned char derived_key[F2FS_MAX_KEY_SIZE])
467{
468	size_t passphrase_size = strlen(passphrase);
469	unsigned char buf[SHA512_LENGTH + F2FS_MAX_PASSPHRASE_SIZE] = {0};
470	unsigned char tempbuf[SHA512_LENGTH] = {0};
471	char final[SHA512_LENGTH] = {0};
472	unsigned char saltbuf[F2FS_MAX_SALT_SIZE + F2FS_MAX_PASSPHRASE_SIZE] = {0};
473	int actual_buf_len = SHA512_LENGTH + passphrase_size;
474	int actual_saltbuf_len = F2FS_MAX_SALT_SIZE + passphrase_size;
475	unsigned int x, y;
476	__u32 *final_u32 = (__u32 *)final;
477	__u32 *temp_u32 = (__u32 *)tempbuf;
478
479	if (passphrase_size > F2FS_MAX_PASSPHRASE_SIZE) {
480		printf("Passphrase size is %zd; max is %d.\n", passphrase_size,
481		       F2FS_MAX_PASSPHRASE_SIZE);
482		exit(1);
483	}
484	if (salt->salt_len > F2FS_MAX_SALT_SIZE) {
485		printf("Salt size is %zd; max is %d.\n", salt->salt_len,
486		       F2FS_MAX_SALT_SIZE);
487		exit(1);
488	}
489	assert(F2FS_MAX_KEY_SIZE <= SHA512_LENGTH);
490
491	memcpy(saltbuf, salt->salt, salt->salt_len);
492	memcpy(&saltbuf[F2FS_MAX_SALT_SIZE], passphrase, passphrase_size);
493
494	memcpy(&buf[SHA512_LENGTH], passphrase, passphrase_size);
495
496	for (x = 0; x < count; ++x) {
497		if (x == 0) {
498			f2fs_sha512(saltbuf, actual_saltbuf_len, tempbuf);
499		} else {
500			/*
501			 * buf: [previous hash || passphrase]
502			 */
503			memcpy(buf, tempbuf, SHA512_LENGTH);
504			f2fs_sha512(buf, actual_buf_len, tempbuf);
505		}
506		for (y = 0; y < (sizeof(final) / sizeof(*final_u32)); ++y)
507			final_u32[y] = final_u32[y] ^ temp_u32[y];
508	}
509	memcpy(derived_key, final, F2FS_MAX_KEY_SIZE);
510}
511
512static int disable_echo(struct termios *saved_settings)
513{
514	struct termios current_settings;
515	int rc = 0;
516
517	rc = tcgetattr(0, &current_settings);
518	if (rc)
519		return rc;
520	*saved_settings = current_settings;
521	current_settings.c_lflag &= ~ECHO;
522	rc = tcsetattr(0, TCSANOW, &current_settings);
523
524	return rc;
525}
526
527static void get_passphrase(char *passphrase, int len)
528{
529	char *p;
530	struct termios current_settings;
531
532	assert(len > 0);
533	disable_echo(&current_settings);
534	p = fgets(passphrase, len, stdin);
535	tcsetattr(0, TCSANOW, &current_settings);
536	printf("\n");
537	if (!p) {
538		printf("Aborting.\n");
539		exit(1);
540	}
541	p = strrchr(passphrase, '\n');
542	if (!p)
543		p = passphrase + len - 1;
544	*p = '\0';
545}
546
547struct keyring_map {
548	char name[4];
549	size_t name_len;
550	int code;
551};
552
553static const struct keyring_map keyrings[] = {
554	{"@us", 3, KEY_SPEC_USER_SESSION_KEYRING},
555	{"@u", 2, KEY_SPEC_USER_KEYRING},
556	{"@s", 2, KEY_SPEC_SESSION_KEYRING},
557	{"@g", 2, KEY_SPEC_GROUP_KEYRING},
558	{"@p", 2, KEY_SPEC_PROCESS_KEYRING},
559	{"@t", 2, KEY_SPEC_THREAD_KEYRING},
560};
561
562static int get_keyring_id(const char *keyring)
563{
564	unsigned int x;
565	char *end;
566
567	/*
568	 * If no keyring is specified, by default use either the user
569	 * session key ring or the session keyring.  Fetching the
570	 * session keyring will return the user session keyring if no
571	 * session keyring has been set.
572	 *
573	 * We need to do this instead of simply adding the key to
574	 * KEY_SPEC_SESSION_KEYRING since trying to add a key to a
575	 * session keyring that does not yet exist will cause the
576	 * kernel to create a session keyring --- which wil then get
577	 * garbage collected as soon as f2fscrypt exits.
578	 *
579	 * The fact that the keyctl system call and the add_key system
580	 * call treats KEY_SPEC_SESSION_KEYRING differently when a
581	 * session keyring does not exist is very unfortunate and
582	 * confusing, but so it goes...
583	 */
584	if (keyring == NULL)
585		return keyctl(KEYCTL_GET_KEYRING_ID,
586			      KEY_SPEC_SESSION_KEYRING, 0);
587	for (x = 0; x < (sizeof(keyrings) / sizeof(keyrings[0])); ++x) {
588		if (strcmp(keyring, keyrings[x].name) == 0) {
589			return keyrings[x].code;
590		}
591	}
592	x = strtoul(keyring, &end, 10);
593	if (*end == '\0') {
594		if (keyctl(KEYCTL_DESCRIBE, x, NULL, 0) < 0)
595			return 0;
596		return x;
597	}
598	return 0;
599}
600
601static void generate_key_ref_str(struct salt *salt)
602{
603	unsigned char key_ref1[SHA512_LENGTH];
604	unsigned char key_ref2[SHA512_LENGTH];
605	int x;
606
607	f2fs_sha512(salt->key, F2FS_MAX_KEY_SIZE, key_ref1);
608	f2fs_sha512(key_ref1, SHA512_LENGTH, key_ref2);
609	memcpy(salt->key_desc, key_ref2, F2FS_KEY_DESCRIPTOR_SIZE);
610	for (x = 0; x < F2FS_KEY_DESCRIPTOR_SIZE; ++x) {
611		sprintf(&salt->key_ref_str[x * 2], "%02x",
612			salt->key_desc[x]);
613	}
614	salt->key_ref_str[F2FS_KEY_REF_STR_BUF_SIZE - 1] = '\0';
615}
616
617static void insert_key_into_keyring(const char *keyring, struct salt *salt)
618{
619	int keyring_id = get_keyring_id(keyring);
620	struct f2fs_encryption_key key;
621	char key_ref_full[F2FS_KEY_DESC_PREFIX_SIZE +
622			  F2FS_KEY_REF_STR_BUF_SIZE];
623	int rc;
624
625	if (keyring_id == 0) {
626		printf("Invalid keyring [%s].\n", keyring);
627		exit(1);
628	}
629	sprintf(key_ref_full, "%s%s", F2FS_KEY_DESC_PREFIX,
630		salt->key_ref_str);
631	rc = keyctl(KEYCTL_SEARCH, keyring_id, F2FS_KEY_TYPE_LOGON,
632		    key_ref_full, 0);
633	if (rc != -1) {
634		if ((options & OPT_QUIET) == 0)
635			printf("Key with descriptor [%s] already exists\n",
636			       salt->key_ref_str);
637		return;
638	} else if ((rc == -1) && (errno != ENOKEY)) {
639		printf("keyctl_search failed: %s\n", strerror(errno));
640		if (errno == -EINVAL)
641			printf("Keyring [%s] is not available.\n", keyring);
642		exit(1);
643	}
644	key.mode = F2FS_ENCRYPTION_MODE_AES_256_XTS;
645	memcpy(key.raw, salt->key, F2FS_MAX_KEY_SIZE);
646	key.size = F2FS_MAX_KEY_SIZE;
647	rc = add_key(F2FS_KEY_TYPE_LOGON, key_ref_full, (void *)&key,
648		     sizeof(key), keyring_id);
649	if (rc == -1) {
650		if (errno == EDQUOT) {
651			printf("Error adding key to keyring; quota exceeded\n");
652		} else {
653			printf("Error adding key with key descriptor [%s]: "
654			       "%s\n", salt->key_ref_str, strerror(errno));
655		}
656		exit(1);
657	} else {
658		if ((options & OPT_QUIET) == 0)
659			printf("Added key with descriptor [%s]\n",
660			       salt->key_ref_str);
661	}
662}
663
664static void get_default_salts(void)
665{
666	FILE	*f = setmntent("/etc/mtab", "r");
667	struct mntent *mnt;
668
669	while (f && ((mnt = getmntent(f)) != NULL)) {
670		if (strcmp(mnt->mnt_type, "f2fs") ||
671		    access(mnt->mnt_dir, R_OK))
672			continue;
673		parse_salt(mnt->mnt_dir, PARSE_FLAGS_NOTSUPP_OK);
674	}
675	endmntent(f);
676}
677
678/* Functions which implement user commands */
679
680struct cmd_desc {
681	const char *cmd_name;
682	void (*cmd_func)(int, char **, const struct cmd_desc *);
683	const char *cmd_desc;
684	const char *cmd_help;
685	int cmd_flags;
686};
687
688#define CMD_HIDDEN 	0x0001
689
690static void do_help(int argc, char **argv, const struct cmd_desc *cmd);
691
692#define add_key_desc "adds a key to the user's keyring"
693#define add_key_help \
694"f2fscrypt add_key -S salt [ -k keyring ] [-v] [-q] [ path ... ]\n\n" \
695"Prompts the user for a passphrase and inserts it into the specified\n" \
696"keyring.  If no keyring is specified, f2fscrypt will use the session\n" \
697"keyring if it exists or the user session keyring if it does not.\n\n" \
698"If one or more directory paths are specified, f2fscrypt will try to\n" \
699"set the policy of those directories to use the key just entered by\n" \
700"the user.\n"
701
702static void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
703{
704	struct salt *salt;
705	char *keyring = NULL;
706	int i, opt, pad = 4;
707	unsigned j;
708
709	while ((opt = getopt(argc, argv, "k:S:p:vq")) != -1) {
710		switch (opt) {
711		case 'k':
712			/* Specify a keyring. */
713			keyring = optarg;
714			break;
715		case 'p':
716			pad = atoi(optarg);
717			break;
718		case 'S':
719			/* Salt value for passphrase. */
720			parse_salt(optarg, 0);
721			break;
722		case 'v':
723			options |= OPT_VERBOSE;
724			break;
725		case 'q':
726			options |= OPT_QUIET;
727			break;
728		default:
729			fprintf(stderr, "Unrecognized option: %c\n", opt);
730			fallthrough;
731		case '?':
732			fputs("USAGE:\n  ", stderr);
733			fputs(cmd->cmd_help, stderr);
734			exit(1);
735		}
736	}
737	if (num_salt == 0)
738		get_default_salts();
739	if (num_salt == 0) {
740		fprintf(stderr, "No salt values available\n");
741		exit(1);
742	}
743	validate_paths(argc, argv, optind);
744	for (i = optind; i < argc; i++)
745		parse_salt(argv[i], PARSE_FLAGS_FORCE_FN);
746	printf("Enter passphrase (echo disabled): ");
747	get_passphrase(in_passphrase, sizeof(in_passphrase));
748	for (j = 0, salt = salt_list; j < num_salt; j++, salt++) {
749		pbkdf2_sha512(in_passphrase, salt,
750			      F2FS_PBKDF2_ITERATIONS, salt->key);
751		generate_key_ref_str(salt);
752		insert_key_into_keyring(keyring, salt);
753	}
754	if (optind != argc)
755		set_policy(NULL, pad, argc, argv, optind);
756	clear_secrets();
757	exit(0);
758}
759
760#define set_policy_desc "sets a policy for directories"
761#define set_policy_help \
762"f2fscrypt set_policy policy path ... \n\n" \
763"Sets the policy for the directories specified on the command line.\n" \
764"All directories must be empty to set the policy; if the directory\n" \
765"already has a policy established, f2fscrypt will validate that it the\n" \
766"policy matches what was specified.  A policy is an encryption key\n" \
767"identifier consisting of 16 hexadecimal characters.\n"
768
769static void do_set_policy(int argc, char **argv, const struct cmd_desc *cmd)
770{
771	struct salt saltbuf;
772	int c, pad = 4;
773
774	while ((c = getopt (argc, argv, "p:")) != EOF) {
775		switch (c) {
776		case 'p':
777			pad = atoi(optarg);
778			break;
779		}
780	}
781
782	if (argc < optind + 2) {
783		fprintf(stderr, "Missing required argument(s).\n\n");
784		fputs("USAGE:\n  ", stderr);
785		fputs(cmd->cmd_help, stderr);
786		exit(1);
787	}
788
789	if ((strlen(argv[optind]) != (F2FS_KEY_DESCRIPTOR_SIZE * 2)) ||
790	    hex2byte(argv[optind], (F2FS_KEY_DESCRIPTOR_SIZE * 2),
791		     saltbuf.key_desc, F2FS_KEY_DESCRIPTOR_SIZE)) {
792		printf("Invalid key descriptor [%s]. Valid characters "
793		       "are 0-9 and a-f, lower case.  "
794		       "Length must be %d.\n",
795		       argv[optind], (F2FS_KEY_DESCRIPTOR_SIZE * 2));
796			exit(1);
797	}
798	validate_paths(argc, argv, optind+1);
799	strcpy(saltbuf.key_ref_str, argv[optind]);
800	set_policy(&saltbuf, pad, argc, argv, optind+1);
801	exit(0);
802}
803
804#define get_policy_desc "get the encryption for directories"
805#define get_policy_help \
806"f2fscrypt get_policy path ... \n\n" \
807"Gets the policy for the directories specified on the command line.\n"
808
809static void do_get_policy(int argc, char **argv, const struct cmd_desc *cmd)
810{
811	struct f2fs_fscrypt_policy policy;
812	struct stat st;
813	int i, j, fd, rc;
814
815	if (argc < 2) {
816		fprintf(stderr, "Missing required argument(s).\n\n");
817		fputs("USAGE:\n  ", stderr);
818		fputs(cmd->cmd_help, stderr);
819		exit(1);
820	}
821
822	for (i = 1; i < argc; i++) {
823		if (stat(argv[i], &st) < 0) {
824			perror(argv[i]);
825			continue;
826		}
827		fd = open(argv[i],
828			  S_ISDIR(st.st_mode) ? O_DIRECTORY : O_RDONLY);
829		if (fd == -1) {
830			perror(argv[i]);
831			exit(1);
832		}
833		rc = ioctl(fd, F2FS_IOC_GET_ENCRYPTION_POLICY, &policy);
834		close(fd);
835		if (rc) {
836			printf("Error getting policy for %s: %s\n",
837			       argv[i], strerror(errno));
838			continue;
839		}
840		printf("%s: ", argv[i]);
841		for (j = 0; j < F2FS_KEY_DESCRIPTOR_SIZE; j++) {
842			printf("%02x", (unsigned char) policy.master_key_descriptor[j]);
843		}
844		fputc('\n', stdout);
845	}
846	exit(0);
847}
848
849#define new_session_desc "give the invoking process a new session keyring"
850#define new_session_help \
851"f2fscrypt new_session\n\n" \
852"Give the invoking process (typically a shell) a new session keyring,\n" \
853"discarding its old session keyring.\n"
854
855static void do_new_session(int argc, char **UNUSED(argv),
856					const struct cmd_desc *cmd)
857{
858	long keyid, ret;
859
860	if (argc > 1) {
861		fputs("Excess arguments\n\n", stderr);
862		fputs(cmd->cmd_help, stderr);
863		exit(1);
864	}
865	keyid = keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL);
866	if (keyid < 0) {
867		perror("KEYCTL_JOIN_SESSION_KEYRING");
868		exit(1);
869	}
870	ret = keyctl(KEYCTL_SESSION_TO_PARENT, NULL);
871	if (ret < 0) {
872		perror("KEYCTL_SESSION_TO_PARENT");
873		exit(1);
874	}
875	printf("Switched invoking process to new session keyring %ld\n", keyid);
876	exit(0);
877}
878
879#define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
880#define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
881
882const struct cmd_desc cmd_list[] = {
883	_CMD(help),
884	CMD(add_key),
885	CMD(get_policy),
886	CMD(new_session),
887	CMD(set_policy),
888	{ NULL, NULL, NULL, NULL, 0 }
889};
890
891static void do_help(int argc, char **argv, const struct cmd_desc *UNUSED(cmd))
892{
893	const struct cmd_desc *p;
894
895	if (argc > 1) {
896		for (p = cmd_list; p->cmd_name; p++) {
897			if (p->cmd_flags & CMD_HIDDEN)
898				continue;
899			if (strcmp(p->cmd_name, argv[1]) == 0) {
900				putc('\n', stdout);
901				fputs("USAGE:\n  ", stdout);
902				fputs(p->cmd_help, stdout);
903				exit(0);
904			}
905		}
906		printf("Unknown command: %s\n\n", argv[1]);
907	}
908
909	fputs("Available commands:\n", stdout);
910	for (p = cmd_list; p->cmd_name; p++) {
911		if (p->cmd_flags & CMD_HIDDEN)
912			continue;
913		printf("  %-20s %s\n", p->cmd_name, p->cmd_desc);
914	}
915	printf("\nTo get more information on a command, "
916	       "type 'f2fscrypt help cmd'\n");
917	exit(0);
918}
919
920int main(int argc, char *argv[])
921{
922	const struct cmd_desc *cmd;
923
924	if (argc < 2)
925		do_help(argc, argv, cmd_list);
926
927	sigcatcher_setup();
928	for (cmd = cmd_list; cmd->cmd_name; cmd++) {
929		if (strcmp(cmd->cmd_name, argv[1]) == 0) {
930			cmd->cmd_func(argc-1, argv+1, cmd);
931			exit(0);
932		}
933	}
934	printf("Unknown command: %s\n\n", argv[1]);
935	do_help(1, argv, cmd_list);
936	return 0;
937}
938