summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ubifs-utils/mkfs.ubifs/mkfs.ubifs.c131
1 files changed, 113 insertions, 18 deletions
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 5be390e..70c306b 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -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;