]> www.infradead.org Git - mtd-utils.git/commitdiff
mkfs.ubifs: Get key descriptor from command line and master key from file
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Thu, 18 Oct 2018 14:37:00 +0000 (16:37 +0200)
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Thu, 1 Nov 2018 11:40:19 +0000 (12:40 +0100)
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c

index 5be390e93da9c56d488fd6986af3ea843eac8367..70c306bdf94ea4f782c982bcea9e6ce9ec595896 100644 (file)
@@ -217,8 +217,7 @@ static struct inum_mapping **hash_table;
 /* Inode creation sequence number */
 static unsigned long long creat_sqnum;
 
-//TODO: add options for double hash and encryption
-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqa";
+static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:";
 
 static const struct option longopts[] = {
        {"root",               1, NULL, 'r'},
@@ -244,6 +243,8 @@ static const struct option longopts[] = {
        {"squash-uids" ,       0, NULL, 'U'},
        {"set-inode-attr",     0, NULL, 'a'},
        {"selinux",            1, NULL, 's'},
+       {"key",                1, NULL, 'K'},
+       {"key-descriptor",     1, NULL, 'b'},
        {NULL, 0, NULL, 0}
 };
 
@@ -288,6 +289,8 @@ static const char *helptext =
 "                         added to the image. The attribute will contain the inode\n"
 "                         number the file has in the generated image.\n"
 "-s, --selinux=FILE       Selinux context file\n"
+"-K, --key=FILE           load an encryption key from a specified file.\n"
+"-b, --key-descriptor=HEX specify the key descriptor as a hex string.\n"
 "-h, --help               display this help text\n\n"
 "Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
 "Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
@@ -582,11 +585,87 @@ static void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
        normsg("");
 }
 
+static int xdigit(int x)
+{
+       if (isupper(x))
+               return x - 'A' + 0x0A;
+       if (islower(x))
+               return x - 'a' + 0x0A;
+       return x - '0';
+}
+
+static int parse_key_descriptor(const char *desc, __u8 *dst)
+{
+       int i, hi, lo;
+
+       for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) {
+               if (!desc[i * 2] || !desc[i * 2 + 1]) {
+                       err_msg("key descriptor '%s' is too short", desc);
+                       return -1;
+               }
+               if (!isxdigit(desc[i * 2]) || !isxdigit(desc[i * 2 + 1])) {
+                       err_msg("invalid key descriptor '%s'", desc);
+                       return -1;
+               }
+
+               hi = xdigit(desc[i * 2]);
+               lo = xdigit(desc[i * 2 + 1]);
+
+               dst[i] = (hi << 4) | lo;
+       }
+
+       if (desc[i * 2]) {
+               err_msg("key descriptor '%s' is too long", desc);
+               return -1;
+       }
+       return 0;
+}
+
+static int load_master_key(const char *key_file)
+{
+       int kf;
+       ssize_t keysize;
+
+       kf = open(key_file, O_RDONLY);
+       if (kf < 0) {
+               sys_errmsg("open '%s'", key_file);
+               return -1;
+       }
+
+       keysize = read(kf, fscrypt_masterkey, sizeof(fscrypt_masterkey));
+       if (keysize < 0) {
+               sys_errmsg("read '%s'", key_file);
+               goto fail;
+       }
+       if (keysize == 0) {
+               err_msg("loading key from '%s': file is empty", key_file);
+               goto fail;
+       }
+
+       close(kf);
+       return 0;
+fail:
+       close(kf);
+       return -1;
+}
+
 static struct fscrypt_context *init_fscrypt_context(unsigned int flags,
-                                               void *master_key_descriptor,
-                                               void *nonce)
+                                               const char *key_file,
+                                               const char *key_descriptor)
 {
-       struct fscrypt_context *new_fctx = xmalloc(sizeof(*new_fctx));
+       __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+       __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+       struct fscrypt_context *new_fctx;
+
+       if (parse_key_descriptor(key_descriptor, master_key_descriptor))
+               return NULL;
+
+       if (load_master_key(key_file))
+               return NULL;
+
+       RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+
+       new_fctx = xmalloc(sizeof(*new_fctx));
 
        new_fctx->format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
        new_fctx->contents_encryption_mode = FS_ENCRYPTION_MODE_AES_128_CBC;
@@ -635,6 +714,7 @@ static int open_ubi(const char *node)
 static int get_options(int argc, char**argv)
 {
        int opt, i;
+       const char *key_file = NULL, *key_desc = NULL;
        const char *tbl_file = NULL;
        struct stat st;
        char *endp;
@@ -812,6 +892,18 @@ static int get_options(int argc, char**argv)
                                return sys_err_msg("bad file context %s\n",
                                                                   context);
                        break;
+               case 'K':
+                       if (key_file) {
+                               return err_msg("key file specified more than once");
+                       }
+                       key_file = optarg;
+                       break;
+               case 'b':
+                       if (key_desc) {
+                               return err_msg("key descriptor specified more than once");
+                       }
+                       key_desc = optarg;
+                       break;
                }
        }
 
@@ -830,6 +922,22 @@ static int get_options(int argc, char**argv)
                        c->max_leb_cnt = c->vi.rsvd_lebs;
        }
 
+       if (key_file || key_desc) {
+               if (!key_file)
+                       return err_msg("no key file specified");
+               if (!key_desc)
+                       return err_msg("no key descriptor specified");
+
+               c->double_hash = 1;
+               c->encrypted = 1;
+
+               root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
+                                               key_file, key_desc);
+               if (!root_fctx)
+                       return -1;
+               print_fscrypt_master_key_descriptor(root_fctx);
+       }
+
        if (c->min_io_size == -1)
                return err_msg("min. I/O unit was not specified "
                               "(use -h for help)");
@@ -2786,8 +2894,6 @@ static int close_target(void)
  */
 static int init(void)
 {
-       __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
-       __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
        int err, i, main_lebs, big_lpt = 0, sz;
 
        c->highest_inum = UBIFS_FIRST_INO;
@@ -2829,17 +2935,6 @@ static int init(void)
        sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE;
        hash_table = xzalloc(sz);
 
-       if (c->encrypted) {
-               RAND_bytes((void *)master_key_descriptor,
-                               FS_KEY_DESCRIPTOR_SIZE);
-               RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
-
-               root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
-                                               master_key_descriptor, nonce);
-               print_fscrypt_master_key_descriptor(root_fctx);
-               c->double_hash = 1;
-       }
-
        err = init_compression();
        if (err)
                return err;