3434#include <sys/utsname.h>
3535#include <unistd.h>
3636
37+ #include "blk-crypto_uapi.h"
3738#include "fscrypt_uapi.h"
3839
3940#ifndef VERSION
@@ -134,6 +135,13 @@ static void __attribute__((__noreturn__)) usage(FILE *out) {
134135 " fscryptctl set_policy <key identifier> <directory>\n"
135136 " Set up an encryption policy on the specified directory with the\n"
136137 " specified key identifier.\n"
138+ " fscryptctl import_hw_wrapped_key <block device>\n"
139+ " Create a hardware-wrapped key by importing a raw key.\n"
140+ " fscryptctl generate_hw_wrapped_key <block device>\n"
141+ " Create a hardware-wrapped key by generating one in hardware.\n"
142+ " fscryptctl prepare_hw_wrapped_key <block device>\n"
143+ " Prepare a hardware-wrapped key to be used by converting it from\n"
144+ " long-term wrapped form to ephemerally-wrapped form.\n"
137145 "\nOptions:\n"
138146 " -h, --help\n"
139147 " print this help screen\n"
@@ -778,6 +786,125 @@ static int cmd_set_policy(int argc, char *const argv[]) {
778786 return EXIT_SUCCESS ;
779787}
780788
789+ static int cmd_import_hw_wrapped_key (int argc , char * const argv []) {
790+ handle_no_options (& argc , & argv );
791+ if (argc != 1 ) {
792+ fputs ("error: must specify a single block device\n" , stderr );
793+ return EXIT_FAILURE ;
794+ }
795+ const char * blkdev = argv [0 ];
796+ int status = EXIT_FAILURE ;
797+
798+ struct blk_crypto_import_key_arg arg = {0 };
799+ uint8_t * raw_key = xzalloc (FSCRYPT_MAX_KEY_SIZE );
800+ uint8_t * lt_key = xzalloc (MAX_WRAPPED_KEY_SIZE );
801+ arg .raw_key_ptr = (uintptr_t )raw_key ;
802+ arg .raw_key_size = read_key (raw_key , FSCRYPT_MAX_KEY_SIZE );
803+ if (arg .raw_key_size == 0 ) {
804+ goto cleanup ;
805+ }
806+ arg .lt_key_ptr = (uintptr_t )lt_key ;
807+ arg .lt_key_size = MAX_WRAPPED_KEY_SIZE ;
808+
809+ int fd = open (blkdev , O_RDONLY | O_CLOEXEC );
810+ if (fd < 0 ) {
811+ fprintf (stderr , "error: opening %s: %s\n" , blkdev , strerror (errno ));
812+ goto cleanup ;
813+ }
814+ if (ioctl (fd , BLKCRYPTOIMPORTKEY , & arg ) != 0 ) {
815+ fprintf (stderr , "error: importing hardware-wrapped key: %s\n" ,
816+ strerror (errno ));
817+ close (fd );
818+ goto cleanup ;
819+ }
820+ close (fd );
821+ if (!full_write (STDOUT_FILENO , lt_key , arg .lt_key_size )) {
822+ goto cleanup ;
823+ }
824+ status = EXIT_SUCCESS ;
825+ cleanup :
826+ wipe_and_free (raw_key , FSCRYPT_MAX_KEY_SIZE );
827+ wipe_and_free (lt_key , MAX_WRAPPED_KEY_SIZE );
828+ return status ;
829+ }
830+
831+ static int cmd_generate_hw_wrapped_key (int argc , char * const argv []) {
832+ handle_no_options (& argc , & argv );
833+ if (argc != 1 ) {
834+ fputs ("error: must specify a single block device\n" , stderr );
835+ return EXIT_FAILURE ;
836+ }
837+ const char * blkdev = argv [0 ];
838+ int status = EXIT_FAILURE ;
839+
840+ struct blk_crypto_generate_key_arg arg = {0 };
841+ uint8_t * lt_key = xzalloc (MAX_WRAPPED_KEY_SIZE );
842+ arg .lt_key_ptr = (uintptr_t )lt_key ;
843+ arg .lt_key_size = MAX_WRAPPED_KEY_SIZE ;
844+
845+ int fd = open (blkdev , O_RDONLY | O_CLOEXEC );
846+ if (fd < 0 ) {
847+ fprintf (stderr , "error: opening %s: %s\n" , blkdev , strerror (errno ));
848+ goto cleanup ;
849+ }
850+ if (ioctl (fd , BLKCRYPTOGENERATEKEY , & arg ) != 0 ) {
851+ fprintf (stderr , "error: generating hardware-wrapped key: %s\n" ,
852+ strerror (errno ));
853+ close (fd );
854+ goto cleanup ;
855+ }
856+ close (fd );
857+ if (!full_write (STDOUT_FILENO , lt_key , arg .lt_key_size )) {
858+ goto cleanup ;
859+ }
860+ status = EXIT_SUCCESS ;
861+ cleanup :
862+ wipe_and_free (lt_key , MAX_WRAPPED_KEY_SIZE );
863+ return status ;
864+ }
865+
866+ static int cmd_prepare_hw_wrapped_key (int argc , char * const argv []) {
867+ handle_no_options (& argc , & argv );
868+ if (argc != 1 ) {
869+ fputs ("error: must specify a single block device\n" , stderr );
870+ return EXIT_FAILURE ;
871+ }
872+ const char * blkdev = argv [0 ];
873+ int status = EXIT_FAILURE ;
874+
875+ struct blk_crypto_prepare_key_arg arg = {0 };
876+ uint8_t * lt_key = xzalloc (MAX_WRAPPED_KEY_SIZE );
877+ uint8_t * eph_key = xzalloc (MAX_WRAPPED_KEY_SIZE );
878+ arg .lt_key_ptr = (uintptr_t )lt_key ;
879+ arg .lt_key_size = read_key (lt_key , MAX_WRAPPED_KEY_SIZE );
880+ if (arg .lt_key_size == 0 ) {
881+ goto cleanup ;
882+ }
883+ arg .eph_key_ptr = (uintptr_t )eph_key ;
884+ arg .eph_key_size = MAX_WRAPPED_KEY_SIZE ;
885+
886+ int fd = open (blkdev , O_RDONLY | O_CLOEXEC );
887+ if (fd < 0 ) {
888+ fprintf (stderr , "error: opening %s: %s\n" , blkdev , strerror (errno ));
889+ goto cleanup ;
890+ }
891+ if (ioctl (fd , BLKCRYPTOPREPAREKEY , & arg ) != 0 ) {
892+ fprintf (stderr , "error: preparing hardware-wrapped key: %s\n" ,
893+ strerror (errno ));
894+ close (fd );
895+ goto cleanup ;
896+ }
897+ close (fd );
898+ if (!full_write (STDOUT_FILENO , eph_key , arg .eph_key_size )) {
899+ goto cleanup ;
900+ }
901+ status = EXIT_SUCCESS ;
902+ cleanup :
903+ wipe_and_free (lt_key , MAX_WRAPPED_KEY_SIZE );
904+ wipe_and_free (eph_key , MAX_WRAPPED_KEY_SIZE );
905+ return status ;
906+ }
907+
781908// -----------------------------------------------------------------------------
782909// The main() function
783910// -----------------------------------------------------------------------------
@@ -786,9 +913,14 @@ static const struct {
786913 const char * name ;
787914 int (* func )(int argc , char * const argv []);
788915} commands [] = {
789- {"add_key" , cmd_add_key }, {"remove_key" , cmd_remove_key },
790- {"key_status" , cmd_key_status }, {"get_policy" , cmd_get_policy },
916+ {"add_key" , cmd_add_key },
917+ {"remove_key" , cmd_remove_key },
918+ {"key_status" , cmd_key_status },
919+ {"get_policy" , cmd_get_policy },
791920 {"set_policy" , cmd_set_policy },
921+ {"import_hw_wrapped_key" , cmd_import_hw_wrapped_key },
922+ {"generate_hw_wrapped_key" , cmd_generate_hw_wrapped_key },
923+ {"prepare_hw_wrapped_key" , cmd_prepare_hw_wrapped_key },
792924};
793925
794926int main (int argc , char * const argv []) {
0 commit comments