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
4651static 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
422431static 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 ;
457484cleanup :
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