124 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
| // SPDX-License-Identifier: MIT
 | |
| /*
 | |
|  * The 'fsverity enable' command
 | |
|  *
 | |
|  * Copyright 2018 Google LLC
 | |
|  *
 | |
|  * Use of this source code is governed by an MIT-style
 | |
|  * license that can be found in the LICENSE file or at
 | |
|  * https://opensource.org/licenses/MIT.
 | |
|  */
 | |
| 
 | |
| #include "fsverity.h"
 | |
| 
 | |
| #include <fcntl.h>
 | |
| #include <getopt.h>
 | |
| #include <limits.h>
 | |
| 
 | |
| static bool read_signature(const char *filename, u8 **sig_ret,
 | |
| 			   u32 *sig_size_ret)
 | |
| {
 | |
| 	struct filedes file = { .fd = -1 };
 | |
| 	u64 file_size;
 | |
| 	u8 *sig = NULL;
 | |
| 	bool ok = false;
 | |
| 
 | |
| 	if (!open_file(&file, filename, O_RDONLY, 0))
 | |
| 		goto out;
 | |
| 	if (!get_file_size(&file, &file_size))
 | |
| 		goto out;
 | |
| 	if (file_size <= 0) {
 | |
| 		error_msg("signature file '%s' is empty", filename);
 | |
| 		goto out;
 | |
| 	}
 | |
| 	if (file_size > 1000000) {
 | |
| 		error_msg("signature file '%s' is too large", filename);
 | |
| 		goto out;
 | |
| 	}
 | |
| 	sig = xmalloc(file_size);
 | |
| 	if (!full_read(&file, sig, file_size))
 | |
| 		goto out;
 | |
| 	*sig_ret = sig;
 | |
| 	*sig_size_ret = file_size;
 | |
| 	sig = NULL;
 | |
| 	ok = true;
 | |
| out:
 | |
| 	filedes_close(&file);
 | |
| 	free(sig);
 | |
| 	return ok;
 | |
| }
 | |
| 
 | |
| static const struct option longopts[] = {
 | |
| 	{"hash-alg",	required_argument, NULL, OPT_HASH_ALG},
 | |
| 	{"block-size",	required_argument, NULL, OPT_BLOCK_SIZE},
 | |
| 	{"salt",	required_argument, NULL, OPT_SALT},
 | |
| 	{"signature",	required_argument, NULL, OPT_SIGNATURE},
 | |
| 	{NULL, 0, NULL, 0}
 | |
| };
 | |
| 
 | |
| /* Enable fs-verity on a file. */
 | |
| int fsverity_cmd_enable(const struct fsverity_command *cmd,
 | |
| 			int argc, char *argv[])
 | |
| {
 | |
| 	struct libfsverity_merkle_tree_params tree_params = { .version = 1 };
 | |
| 	u8 *sig = NULL;
 | |
| 	u32 sig_size = 0;
 | |
| 	struct filedes file;
 | |
| 	int status;
 | |
| 	int c;
 | |
| 
 | |
| 	while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
 | |
| 		switch (c) {
 | |
| 		case OPT_HASH_ALG:
 | |
| 		case OPT_BLOCK_SIZE:
 | |
| 		case OPT_SALT:
 | |
| 			if (!parse_tree_param(c, optarg, &tree_params))
 | |
| 				goto out_usage;
 | |
| 			break;
 | |
| 		case OPT_SIGNATURE:
 | |
| 			if (sig != NULL) {
 | |
| 				error_msg("--signature can only be specified once");
 | |
| 				goto out_usage;
 | |
| 			}
 | |
| 			if (!read_signature(optarg, &sig, &sig_size))
 | |
| 				goto out_err;
 | |
| 			break;
 | |
| 		default:
 | |
| 			goto out_usage;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	argv += optind;
 | |
| 	argc -= optind;
 | |
| 
 | |
| 	if (argc != 1)
 | |
| 		goto out_usage;
 | |
| 
 | |
| 	if (!open_file(&file, argv[0], O_RDONLY, 0))
 | |
| 		goto out_err;
 | |
| 
 | |
| 	if (libfsverity_enable_with_sig(file.fd, &tree_params, sig, sig_size)) {
 | |
| 		error_msg_errno("FS_IOC_ENABLE_VERITY failed on '%s'",
 | |
| 				file.name);
 | |
| 		filedes_close(&file);
 | |
| 		goto out_err;
 | |
| 	}
 | |
| 	if (!filedes_close(&file))
 | |
| 		goto out_err;
 | |
| 
 | |
| 	status = 0;
 | |
| out:
 | |
| 	destroy_tree_params(&tree_params);
 | |
| 	free(sig);
 | |
| 	return status;
 | |
| 
 | |
| out_err:
 | |
| 	status = 1;
 | |
| 	goto out;
 | |
| 
 | |
| out_usage:
 | |
| 	usage(cmd, stderr);
 | |
| 	status = 2;
 | |
| 	goto out;
 | |
| }
 |