diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2018-10-18 16:37:00 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2018-11-01 12:40:19 +0100 | 
| commit | 41453928c0d3613b6ee6823d291b44dcd2f73126 (patch) | |
| tree | 95225ba200a11db34bf13ee609880cafd16630f9 /ubifs-utils | |
| parent | f4efc8b7c4989e93629dad845bfe45c47ca1d03a (diff) | |
mkfs.ubifs: Get key descriptor from command line and master key from file
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'ubifs-utils')
| -rw-r--r-- | ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 131 | 
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; | 
