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, ¤t_settings); 518 if (rc) 519 return rc; 520 *saved_settings = current_settings; 521 current_settings.c_lflag &= ~ECHO; 522 rc = tcsetattr(0, TCSANOW, ¤t_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(¤t_settings); 534 p = fgets(passphrase, len, stdin); 535 tcsetattr(0, TCSANOW, ¤t_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